From 80bc8c7e9e5e374e330491f97e397d47e390579a Mon Sep 17 00:00:00 2001 From: Scott Date: Thu, 29 Oct 2020 13:00:02 +1100 Subject: [PATCH] Trade history, recent trades, live trade processing and storage (#558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * End of day commit moving packages and setting foundation into how trade processing will go * Conformity * tdd candle generation based on received trade data, renames orderbookbuffer back to buffer for now... * Formalises test functions and designs the trade processor * Theoretical amending old candles to allow any trades that were part of an old processed candle to be more accurate. Saving of candles will only occur on previous cycles, extending memory usage a bit longer * Figures out sqlboiler for sqlite. Updates websocket entries to process trade data * One more trade data * Adds more exchange support * Adds PSQL stuff * Begins creating sql implementation * End of day commit. Helper functions and understanding sql usage in GCT * Adds delete and cleans up table design * Finishes trades conceptually. Awaits candle data update in order to translate trades to candles * Initial handling of trades in coinbene * Proto * Fixing of some bugs, attempting to address coinbene asset type ws issues * Fixes up coinbene websocket implementation for the most part * finalises coinbene websocket implementation. Adds new ability to parse currencies without a delimiter * Implements rpc commands and adds testing * updates the following to be compatible with trade data update: Theoretical amending old candles to allow any trades that were part of an old processed candle to be more accurate. Saving of candles will only occur on previous cycles, extending memory usage a bit longer * Changes trade to be its own entity rather than attached to a websocket. * Adds coverage to trades. Changes signature of `AddTradesToBuffer` to return error. Now automatically shuts down without need for channel listening. Will automatically start up again if it gets data * Implements trade fetching at the wrapper level for a bunch of exchanges. Adds trade id to script updoot. Probably breaking change * Implements trade fetching for all wrappers hurray hurrah. Updates all the tests * Adds new interface func to get recent trades. Ensures GetExchangeHistory continues until conditions are met * Adds new readme, tests all new wrapper endpoints, updates exchange_wrapper_issues to test new endpoints. Updates exchange_wrapper_coverage with new coverage... Fixes lame bug causing wrapper tests to fail from being poorly setup. Adds loopy loop to ensure that all data is captured when requesting exchange history * Bugfix on psql migrations. Rebases latest changes, updates table design to use base and quote, updates trades to use exchange_name_id * Adds new config field for saving trades to the database per exchange. Now exits trade processing when trade saving is not enabled. Similarly for wrapper, does not save if not enabled * Minor bitfinex trade fixes. continues on buffer processing errors, now saves transactionid to the db * Adds support for generating candles from candlesextended. May extend it further, idk * Updates trade candles to be able to fill missing data with trades. Adds more tests. Also does a thing where you can forcefully override a candle based on internal trade data instead of API data * Fixes bug where force deletions did not follow up with insertions. Adds force to candle commands * Fixes specific exchange based issues. Extends recent trades to 24 hours where possible * Fixes issue with saved tests. Fixes tests for trades. Adds parallel to tests. Pre-fixes people's nits * Adds new GRPC functions to find out what data is missing from trades and candles. Fixes some assumptions from missing period code. * Adds unique constraint. Fixes up niggling issues for wrappers and websockets * Fixes issues with using unix times in the database trying to retrieve data via the CLI. Reduces save time to 15 seconds * Updates trades to use timestamps instead of int64 unix * Adds missing FTX wrapper implementation. Regens docs * Linting the linters. Updating readme * Adds new command to set whether an exchange can process trades * Doc update * Adds recent trades and historic trade endpoints to grpc * formats pair_test.go to appease linter gods * Addresses data race. Removes logging of missing intervals on unrelated function (now that it has its own rpc command). The buffer time isnt customisable, but I don't feel it needs to be at a config level at all really. * Fixes a few niterinos regarding spacing, type conversion, a weird Bitmex 0 trade value error, unsubscriptions and cli command references * Reduces map lookups. Adds base func and moves wrappers to use it * Uses better currency formatter. Adds time based validation to trade history. Reverts configtest.json * Reverts config and updates test names. Also WAYYYYY LESS SPAMMY * oopsie doopsie missed a whoopsie * mint flavoured lint * Fixes issues caused by rebase * Fixes issue with timestamps not converting properly from command to RPCServer. Adds new error type. Adds shorthand entries to some commands. Removes os.Exit from tests. Makes Gemini test rolling. Adds enabled exchange check to RPC function. Escapes timestamp on bitstamp. Renames var * fixes whoopsie oopsie doopsie I forgot to remove code shoopsie * missed a line * :tada: :tada: :tada:Breaks everything in an end of day commit :tada: :tada: :tada: * Modifies function 'createlocaloffset' to return a string instead. Uses strings for all time based start and end commands. Uses UTC times in RPC server and updates SQLITE to use formatted time based queries * Adds concurrency-safe way of changing SaveTradeData and checking it. Fixes embarrassing typo * End of day fix, adds bitfinex update to loop until either the return trades shows no new dates, or meets specifications. Fixes egregious typo * Improves testing and handling of historical trades function * Fixes tests after latest changes * Fix potential fatal err now that db is enabled in test config now * Fixes up some database settings to use a local engine instead of global var * DELICIOUS LINT CHOCOLATE FIXES * Fixes data race by slashing competitor's tyres * Adds mock test fixes to allow for live and stored data test * Removes verbosity in engine level tests. Adds new timezone format to highlight the timezone for RPC functions. Removes reference to Preix index fund * Oopsie doopsie, fixed a whoopsie * Loggers can no longer do data drag races on my lawn :older_man: * Removes bad lock * Addresses command nits. End of day conceptual commit, trying to calculate spans of time in the context of missing periods. Tests will fail * Adds new stream response for retrieving trade history as it can take time to do. Unsuccessfully attempts to simplify time range calculation for missing trades response * Adds new timeperiods package to calculate time periods, time ranges and whether data is in those ranges. Removes kline basic implementation of same concept * Fixes lint issues. Fixes test. Moves trade cli commands to their own trade subcommands * Updates lakebtc to no longer have gethistorictrades as it is unsupported. Adds more validation to rpc functions * Removes requirement to have trades when testing trade wrapper functions. Doesn't really prove it works if there are no trades for a given currency in a time period. * Addresses nits, runs linting fix and ensures a test is consistent * Fix merge issues * Moves sort to timeperiods. Adds test coverage. Fixes typo * Removes log package in CLI * Fixes `GetTrades` url * Reorders all instances of validation occuring after settingup RPC connection * Fixes test to ensure that it is setup before testing that it is setup * Fixed issue with bool retrieval. Removes double append * Fixes Binance times, fixes bitfinex sell sides, fixes huobi times, sorts all responses * Fixes poloniex trade id consistency. Makes recent trade for poloniex consistent with others (15 minutes). Fixes coinbene. Fixes localbitcoins to use quote currency. Fixes coinut times. Updates huobi trade id, saves okgroup trades. Fixes bid and ask to buy and sell * Removes websocket trades for lakebtc as it did not meet our requirements for processing. Adds new constraints to the database to ensure we have uniqueness on trades where ID doesn't exist and doesn't trigger errors for trades where the tid does * Fixes migration for postgres to downscale properly * Really really fixes the psql index changes * Fixes broken tests * Now with working tests and no pocket lint * Makes the side column nullable with no more constraint for it. adds migrations and runs generation. comments lakebtc * Lint & Sprüngli * Updates zb to use more appropriate side * Fixes oopsie * Attempts to address a data race from globals * Fixes build * Fixes missed regen rpc files * Updates readme to point to trade readme. Fixes exchange_wrapper_coverage wrapper count and untested panics, tests bitfinex funding pair test for `fUSD`, adds shiny new param `tradeprocessinginterval` * mint flavoured lint * Uses the real default to set the default value by default * Fixes some extra tests surrounding email sending and number incompatibility * Reverts test config * re-adds gom2/usdt currency * Fixes typo, don't look! * Fixes minor codelingo pickups * Adds more precision to handling of trade data from Kraken. Expands test * interface christmas tree * lint --- CONTRIBUTORS | 2 +- README.md | 19 +- cmd/apichecker/apicheck.go | 2 + cmd/apichecker/apicheck_test.go | 6 +- .../exchanges_trade_readme.tmpl | 78 + .../root_templates/root_readme.tmpl | 9 +- cmd/exchange_template/test_file.tmpl | 122 +- cmd/exchange_template/wrapper_file.tmpl | 12 +- cmd/exchange_wrapper_coverage/main.go | 32 +- cmd/exchange_wrapper_issues/main.go | 219 +- cmd/gctcli/commands.go | 403 +- cmd/gctcli/main.go | 2 + cmd/gctcli/trades.go | 765 + common/common.go | 5 +- common/timeperiods/timeperiods.go | 148 + common/timeperiods/timeperiods_test.go | 188 + common/timeperiods/timeperiods_types.go | 32 + communications/smtpservice/smtpservice.go | 7 + config/config_types.go | 1 + currency/pair.go | 22 + currency/pair_test.go | 83 + .../20200909083123_trade/postgres.sql | 20 + .../20200909083123_trade/sqlite3.sql | 20 + .../postgres.sql | 14 + .../sqlite3.sql | 47 + .../postgres.sql | 23 + .../sqlite3.sql | 55 + database/models/postgres/boil_table_names.go | 2 + database/models/postgres/exchange.go | 172 + database/models/postgres/exchange_test.go | 153 + database/models/postgres/trade.go | 1071 + database/models/postgres/trade_test.go | 841 + database/models/sqlite3/boil_suites_test.go | 22 + database/models/sqlite3/boil_table_names.go | 4 + database/models/sqlite3/exchange.go | 166 + database/models/sqlite3/exchange_test.go | 112 + database/models/sqlite3/trade.go | 994 + database/models/sqlite3/trade_test.go | 793 + database/models/sqlite3/withdrawal_crypto.go | 23 - database/repository/candle/candle.go | 90 +- database/repository/candle/candle_test.go | 11 +- database/repository/candle/candle_types.go | 2 +- database/repository/exchange/exchange.go | 5 +- database/repository/trade/trade.go | 359 + database/repository/trade/trade_test.go | 201 + database/repository/trade/trade_types.go | 19 + database/testhelpers/test_helpers.go | 2 + engine/database.go | 30 +- engine/engine.go | 15 +- engine/engine_types.go | 1 + engine/events_test.go | 3 - engine/exchange.go | 28 +- engine/fake_exchange_test.go | 6 +- engine/helpers.go | 2 +- engine/routines.go | 8 - engine/routines_test.go | 4 - engine/rpcserver.go | 686 +- engine/rpcserver_test.go | 787 + engine/syncer_test.go | 1 - exchanges/alphapoint/alphapoint_test.go | 25 + exchanges/alphapoint/alphapoint_wrapper.go | 10 +- exchanges/binance/binance.go | 4 +- exchanges/binance/binance_test.go | 30 +- exchanges/binance/binance_types.go | 2 +- exchanges/binance/binance_websocket.go | 21 +- exchanges/binance/binance_wrapper.go | 43 +- exchanges/bitfinex/bitfinex.go | 5 +- exchanges/bitfinex/bitfinex_test.go | 73 + exchanges/bitfinex/bitfinex_types.go | 2 +- exchanges/bitfinex/bitfinex_websocket.go | 63 +- exchanges/bitfinex/bitfinex_wrapper.go | 80 +- exchanges/bitflyer/bitflyer_test.go | 28 +- exchanges/bitflyer/bitflyer_wrapper.go | 53 +- exchanges/bithumb/bithumb_test.go | 24 + exchanges/bithumb/bithumb_wrapper.go | 51 +- exchanges/bitmex/bitmex_test.go | 34 +- exchanges/bitmex/bitmex_websocket.go | 36 +- exchanges/bitmex/bitmex_wrapper.go | 83 +- exchanges/bitstamp/bitstamp.go | 24 +- exchanges/bitstamp/bitstamp_test.go | 32 +- exchanges/bitstamp/bitstamp_types.go | 2 +- exchanges/bitstamp/bitstamp_websocket.go | 16 +- exchanges/bitstamp/bitstamp_wrapper.go | 47 +- exchanges/bittrex/bittrex_test.go | 25 + exchanges/bittrex/bittrex_wrapper.go | 53 +- exchanges/btcmarkets/btcmarkets.go | 2 +- exchanges/btcmarkets/btcmarkets_test.go | 25 + exchanges/btcmarkets/btcmarkets_websocket.go | 24 +- exchanges/btcmarkets/btcmarkets_wrapper.go | 50 +- exchanges/btse/btse.go | 14 +- exchanges/btse/btse_test.go | 102 +- exchanges/btse/btse_types.go | 2 +- exchanges/btse/btse_websocket.go | 14 +- exchanges/btse/btse_wrapper.go | 88 +- exchanges/coinbasepro/coinbasepro_test.go | 25 + .../coinbasepro/coinbasepro_websocket.go | 107 +- exchanges/coinbasepro/coinbasepro_wrapper.go | 48 +- exchanges/coinbene/coinbene.go | 3 +- exchanges/coinbene/coinbene_test.go | 180 +- exchanges/coinbene/coinbene_types.go | 66 +- exchanges/coinbene/coinbene_websocket.go | 302 +- exchanges/coinbene/coinbene_wrapper.go | 44 +- exchanges/coinut/coinut.go | 2 +- exchanges/coinut/coinut_test.go | 26 + exchanges/coinut/coinut_types.go | 23 +- exchanges/coinut/coinut_websocket.go | 50 +- exchanges/coinut/coinut_wrapper.go | 52 +- exchanges/exchange.go | 38 + exchanges/exchange_test.go | 55 + exchanges/exchange_types.go | 18 +- exchanges/exmo/exmo_test.go | 25 + exchanges/exmo/exmo_types.go | 2 +- exchanges/exmo/exmo_wrapper.go | 49 +- exchanges/ftx/ftx.go | 10 +- exchanges/ftx/ftx_test.go | 51 +- exchanges/ftx/ftx_websocket.go | 11 +- exchanges/ftx/ftx_wrapper.go | 103 +- exchanges/gateio/gateio.go | 12 + exchanges/gateio/gateio_test.go | 32 + exchanges/gateio/gateio_types.go | 19 + exchanges/gateio/gateio_websocket.go | 26 +- exchanges/gateio/gateio_wrapper.go | 48 +- exchanges/gemini/gemini.go | 14 +- exchanges/gemini/gemini_test.go | 32 +- exchanges/gemini/gemini_types.go | 3 +- exchanges/gemini/gemini_websocket.go | 15 +- exchanges/gemini/gemini_wrapper.go | 72 +- exchanges/hitbtc/hitbtc.go | 38 +- exchanges/hitbtc/hitbtc_test.go | 31 +- exchanges/hitbtc/hitbtc_websocket.go | 36 +- exchanges/hitbtc/hitbtc_wrapper.go | 69 +- exchanges/huobi/huobi.go | 8 +- exchanges/huobi/huobi_test.go | 26 +- exchanges/huobi/huobi_types.go | 4 +- exchanges/huobi/huobi_websocket.go | 28 +- exchanges/huobi/huobi_wrapper.go | 50 +- exchanges/interfaces.go | 4 +- exchanges/itbit/itbit.go | 6 +- exchanges/itbit/itbit_test.go | 25 + exchanges/itbit/itbit_types.go | 8 +- exchanges/itbit/itbit_wrapper.go | 43 +- exchanges/kline/kline_datastorage.go | 11 +- exchanges/kline/kline_test.go | 11 +- exchanges/kline/kline_types.go | 15 + exchanges/kraken/kraken.go | 106 +- exchanges/kraken/kraken_test.go | 30 + exchanges/kraken/kraken_websocket.go | 73 +- exchanges/kraken/kraken_wrapper.go | 46 +- exchanges/lakebtc/lakebtc.go | 5 +- exchanges/lakebtc/lakebtc_test.go | 38 +- exchanges/lakebtc/lakebtc_types.go | 2 +- exchanges/lakebtc/lakebtc_websocket.go | 54 +- exchanges/lakebtc/lakebtc_wrapper.go | 43 +- exchanges/lbank/lbank.go | 10 +- exchanges/lbank/lbank_test.go | 34 +- exchanges/lbank/lbank_wrapper.go | 73 +- exchanges/localbitcoins/localbitcoins.go | 2 +- exchanges/localbitcoins/localbitcoins_test.go | 32 + .../localbitcoins/localbitcoins_wrapper.go | 42 +- exchanges/mock/README.md | 422 +- exchanges/okcoin/okcoin_test.go | 24 + exchanges/okcoin/okcoin_wrapper.go | 50 + exchanges/okex/okex.go | 2 +- exchanges/okex/okex_test.go | 28 +- exchanges/okex/okex_wrapper.go | 98 + exchanges/okgroup/okgroup_types.go | 6 +- exchanges/okgroup/okgroup_websocket.go | 22 +- exchanges/okgroup/okgroup_wrapper.go | 11 +- exchanges/poloniex/poloniex.go | 10 +- exchanges/poloniex/poloniex_test.go | 37 +- exchanges/poloniex/poloniex_websocket.go | 33 +- exchanges/poloniex/poloniex_wrapper.go | 75 +- exchanges/stream/stream_types.go | 12 - exchanges/trade/README.md | 112 + exchanges/trade/trade.go | 271 + exchanges/trade/trade_test.go | 251 + exchanges/trade/trade_types.go | 57 + exchanges/yobit/yobit.go | 28 +- exchanges/yobit/yobit_test.go | 25 +- exchanges/yobit/yobit_types.go | 10 +- exchanges/yobit/yobit_wrapper.go | 48 +- exchanges/zb/zb.go | 9 + exchanges/zb/zb_test.go | 37 + exchanges/zb/zb_types.go | 9 + exchanges/zb/zb_websocket.go | 40 +- exchanges/zb/zb_websocket_types.go | 12 +- exchanges/zb/zb_wrapper.go | 49 +- gctrpc/rpc.pb.go | 3270 ++- gctrpc/rpc.pb.gw.go | 621 +- gctrpc/rpc.proto | 2540 +-- gctrpc/rpc.swagger.json | 557 +- gctscript/vm/vm_test.go | 2 + log/logger_setup.go | 3 + log/logger_test.go | 7 +- log/loggers.go | 11 +- log/sublogger_types.go | 1 + main.go | 2 + testdata/configtest.json | 2 +- testdata/http_mock/binance/binance.json | 9007 ++++++++ testdata/http_mock/bitstamp/bitstamp.json | 445 + testdata/http_mock/gemini/gemini.json | 18032 ++++++++++++++++ .../localbitcoins/localbitcoins.json | 3011 +++ testdata/http_mock/poloniex/poloniex.json | 4788 ++-- testdata/http_mock/zb/zb.json | 411 + 204 files changed, 51177 insertions(+), 6023 deletions(-) create mode 100644 cmd/documentation/exchanges_templates/exchanges_trade_readme.tmpl create mode 100644 cmd/gctcli/trades.go create mode 100644 common/timeperiods/timeperiods.go create mode 100644 common/timeperiods/timeperiods_test.go create mode 100644 common/timeperiods/timeperiods_types.go create mode 100644 database/migrations/20200909083123_trade/postgres.sql create mode 100644 database/migrations/20200909083123_trade/sqlite3.sql create mode 100644 database/migrations/20201013122046_ammend_trade_constraints/postgres.sql create mode 100644 database/migrations/20201013122046_ammend_trade_constraints/sqlite3.sql create mode 100644 database/migrations/20201013151813_trade_nullable_sides/postgres.sql create mode 100644 database/migrations/20201013151813_trade_nullable_sides/sqlite3.sql create mode 100644 database/models/postgres/trade.go create mode 100644 database/models/postgres/trade_test.go create mode 100644 database/models/sqlite3/trade.go create mode 100644 database/models/sqlite3/trade_test.go create mode 100644 database/repository/trade/trade.go create mode 100644 database/repository/trade/trade_test.go create mode 100644 database/repository/trade/trade_types.go create mode 100644 engine/rpcserver_test.go create mode 100644 exchanges/trade/README.md create mode 100644 exchanges/trade/trade.go create mode 100644 exchanges/trade/trade_test.go create mode 100644 exchanges/trade/trade_types.go diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a82c1867..89da9e13 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -10,9 +10,9 @@ vadimzhukck | https://github.com/vadimzhukck MadCozBadd | https://github.com/MadCozBadd 140am | https://github.com/140am marcofranssen | https://github.com/marcofranssen -dackroyd | https://github.com/dackroyd Rots | https://github.com/Rots vazha | https://github.com/vazha +dackroyd | https://github.com/dackroyd cranktakular | https://github.com/cranktakular woshidama323 | https://github.com/woshidama323 crackcomm | https://github.com/crackcomm diff --git a/README.md b/README.md index c17441f9..6b407564 100644 --- a/README.md +++ b/README.md @@ -26,21 +26,21 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | BitMEX | Yes | Yes | NA | | Bitstamp | Yes | Yes | No | | Bittrex | Yes | No | NA | -| BTCMarkets | Yes | No | NA | +| BTCMarkets | Yes | Yes | NA | | BTSE | Yes | Yes | NA | +| CoinbasePro | Yes | Yes | No| +| Coinbene | Yes | Yes | No | | COINUT | Yes | Yes | NA | | Exmo | Yes | NA | NA | | FTX | Yes | Yes | No | -| CoinbasePro | Yes | Yes | No| -| Coinbene | Yes | No | No | | GateIO | Yes | Yes | NA | | Gemini | Yes | Yes | No | | HitBTC | Yes | Yes | No | | Huobi.Pro | Yes | Yes | NA | | ItBit | Yes | NA | No | | Kraken | Yes | Yes | NA | +| LakeBTC | Yes | Yes | NA | | Lbank | Yes | No | NA | -| LakeBTC | Yes | No | NA | | LocalBitcoins | Yes | NA | NA | | OKCoin International | Yes | Yes | No | | OKEX | Yes | Yes | No | @@ -76,6 +76,7 @@ However, we welcome pull requests for any exchange which does not match this cri + Basic event trigger system. + OHLCV/Candle retrieval support. See [OHLCV](/docs/OHLCV.md). + Scripting support. See [gctscript](/gctscript/README.md). ++ Recent and historic trade processing. See [trades](/exchanges/trade/README.md). + WebGUI (discontinued). ## Planned Features @@ -142,18 +143,18 @@ Binaries will be published once the codebase reaches a stable condition. |User|Contribution Amount| |--|--| | [thrasher-](https://github.com/thrasher-) | 643 | -| [shazbert](https://github.com/shazbert) | 196 | -| [gloriousCode](https://github.com/gloriousCode) | 170 | -| [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 69 | +| [shazbert](https://github.com/shazbert) | 197 | +| [gloriousCode](https://github.com/gloriousCode) | 171 | +| [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 70 | | [xtda](https://github.com/xtda) | 47 | | [ermalguni](https://github.com/ermalguni) | 14 | | [vadimzhukck](https://github.com/vadimzhukck) | 10 | | [MadCozBadd](https://github.com/MadCozBadd) | 9 | | [140am](https://github.com/140am) | 8 | | [marcofranssen](https://github.com/marcofranssen) | 8 | +| [Rots](https://github.com/Rots) | 7 | +| [vazha](https://github.com/vazha) | 7 | | [dackroyd](https://github.com/dackroyd) | 5 | -| [Rots](https://github.com/Rots) | 5 | -| [vazha](https://github.com/vazha) | 5 | | [cranktakular](https://github.com/cranktakular) | 5 | | [woshidama323](https://github.com/woshidama323) | 3 | | [crackcomm](https://github.com/crackcomm) | 3 | diff --git a/cmd/apichecker/apicheck.go b/cmd/apichecker/apicheck.go index 2a987d78..b5d50dcc 100644 --- a/cmd/apichecker/apicheck.go +++ b/cmd/apichecker/apicheck.go @@ -101,7 +101,9 @@ func main() { flag.Parse() var err error c := log.GenDefaultSettings() + log.RWM.Lock() log.GlobalLogConfig = &c + log.RWM.Unlock() log.SetupGlobalLogger() configData, err = readFileData(jsonFile) if err != nil { diff --git a/cmd/apichecker/apicheck_test.go b/cmd/apichecker/apicheck_test.go index 87513bb6..714786a4 100644 --- a/cmd/apichecker/apicheck_test.go +++ b/cmd/apichecker/apicheck_test.go @@ -28,7 +28,9 @@ func TestMain(m *testing.M) { testMode = true c := log.GenDefaultSettings() c.Enabled = convert.BoolPtr(true) + log.RWM.Lock() log.GlobalLogConfig = &c + log.RWM.Unlock() log.Infoln(log.Global, "set verbose to true for more detailed output") var err error configData, err = readFileData(jsonFile) @@ -158,7 +160,7 @@ func TestAdd(t *testing.T) { } err := addExch("FalseName", htmlScrape, data2, false) if err == nil { - t.Log("expected an error due to invalid path being parsed in") + t.Error("expected an error due to invalid path being parsed in") } } @@ -635,7 +637,7 @@ func TestWriteAuthVars(t *testing.T) { trelloCardID = "jdsfl" err := writeAuthVars(testMode) if err != nil { - t.Log(err) + t.Error(err) } } } diff --git a/cmd/documentation/exchanges_templates/exchanges_trade_readme.tmpl b/cmd/documentation/exchanges_templates/exchanges_trade_readme.tmpl new file mode 100644 index 00000000..0ef0569a --- /dev/null +++ b/cmd/documentation/exchanges_templates/exchanges_trade_readme.tmpl @@ -0,0 +1,78 @@ +{{define "exchanges trade" -}} +{{template "header" .}} +## Current Features for {{.Name}} + ++ The trade package contains a processor for both REST and websocket trade history processing + + Its primary purpose is to collect trade data from multiple sources and save it to the database's trade table + + If you do not have database enabled, then trades will not be processed + +### Requirements to save a trade to the database ++ Database has to be enabled ++ Under `config.json`, under your selected exchange, enable the field `saveTradeData` + + This will enable trade processing to occur for that specific exchange + + This can also be done via gRPC under the `SetExchangeTradeProcessing` command + +### Usage ++ To send trade data to be processed, use the following example: +``` +err := trade.AddTradesToBuffer(b.Name, trade.Data{ + Exchange: b.Name, + TID: strconv.FormatInt(tradeData[i].TID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTS, +}) +``` +_b in this context is an `IBotExchange` implemented struct_ + +### Rules ++ If the trade processor has not started, it will automatically start upon being sent trade data. ++ The processor will add all received trades to a buffer ++ After 15 seconds, the trade processor will parse and save all trades on the buffer to the trade table + + This is to save on constant writing to the database. Trade data, especially when received via websocket would cause massive issues on the round trip of saving data for every trade ++ If the processor has not received any trades in that 15 second timeframe, it will shut down. + + Sending trade data to it later will automatically start it up again + + +## Exchange Support Table + +| Exchange | Recent Trades via REST | Live trade updates via Websocket | Trade history via REST | +|----------|------|-----------|-----| +| Alphapoint | No | No | No | +| Binance| Yes | Yes | No | +| Bitfinex | Yes | Yes | Yes | +| Bitflyer | Yes | No | No | +| Bithumb | Yes | NA | No | +| BitMEX | Yes | Yes | Yes | +| Bitstamp | Yes | Yes | No | +| Bittrex | Yes | No | No | +| BTCMarkets | Yes | Yes | No | +| BTSE | Yes | Yes | No | +| Coinbene | Yes | Yes | No | +| CoinbasePro | Yes | Yes | No| +| COINUT | Yes | Yes | No | +| Exmo | Yes | NA | No | +| FTX | Yes | Yes | Yes | +| GateIO | Yes | Yes | No | +| Gemini | Yes | Yes | Yes | +| HitBTC | Yes | Yes | Yes | +| Huobi.Pro | Yes | Yes | No | +| ItBit | Yes | NA | No | +| Kraken | Yes | Yes | No | +| LakeBTC | Yes | No | No | +| Lbank | Yes | No | Yes | +| LocalBitcoins | Yes | NA | No | +| OKCoin International | Yes | Yes | No | +| OKEX | Yes | Yes | No | +| Poloniex | Yes | Yes | Yes | +| Yobit | Yes | NA | No | +| ZB.COM | Yes | Yes | No | + + +### Please click GoDocs chevron above to view current GoDoc information for this package +{{template "contributions"}} +{{template "donations" .}} +{{end}} diff --git a/cmd/documentation/root_templates/root_readme.tmpl b/cmd/documentation/root_templates/root_readme.tmpl index 11cf2397..4955b195 100644 --- a/cmd/documentation/root_templates/root_readme.tmpl +++ b/cmd/documentation/root_templates/root_readme.tmpl @@ -27,21 +27,21 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader | BitMEX | Yes | Yes | NA | | Bitstamp | Yes | Yes | No | | Bittrex | Yes | No | NA | -| BTCMarkets | Yes | No | NA | +| BTCMarkets | Yes | Yes | NA | | BTSE | Yes | Yes | NA | +| CoinbasePro | Yes | Yes | No| +| Coinbene | Yes | Yes | No | | COINUT | Yes | Yes | NA | | Exmo | Yes | NA | NA | | FTX | Yes | Yes | No | -| CoinbasePro | Yes | Yes | No| -| Coinbene | Yes | No | No | | GateIO | Yes | Yes | NA | | Gemini | Yes | Yes | No | | HitBTC | Yes | Yes | No | | Huobi.Pro | Yes | Yes | NA | | ItBit | Yes | NA | No | | Kraken | Yes | Yes | NA | +| LakeBTC | Yes | Yes | NA | | Lbank | Yes | No | NA | -| LakeBTC | Yes | No | NA | | LocalBitcoins | Yes | NA | NA | | OKCoin International | Yes | Yes | No | | OKEX | Yes | Yes | No | @@ -77,6 +77,7 @@ However, we welcome pull requests for any exchange which does not match this cri + Basic event trigger system. + OHLCV/Candle retrieval support. See [OHLCV](/docs/OHLCV.md). + Scripting support. See [gctscript](/gctscript/README.md). ++ Recent and historic trade processing. See [trades](/exchanges/trade/README.md). + WebGUI (discontinued). ## Planned Features diff --git a/cmd/exchange_template/test_file.tmpl b/cmd/exchange_template/test_file.tmpl index 10afb3ad..8312abd7 100644 --- a/cmd/exchange_template/test_file.tmpl +++ b/cmd/exchange_template/test_file.tmpl @@ -1,61 +1,61 @@ -{{define "test"}} -package {{.Name}} - -import ( - "log" - "os" - "testing" - - "github.com/thrasher-corp/gocryptotrader/config" - exchange "github.com/thrasher-corp/gocryptotrader/exchanges" -) - -// Please supply your own keys here to do authenticated endpoint testing -const ( - apiKey = "" - apiSecret = "" - canManipulateRealOrders = false -) - -var {{.Variable}} {{.CapitalName}} - -func TestMain(m *testing.M) { - {{.Variable}}.SetDefaults() - cfg := config.GetConfig() - err := cfg.LoadConfig("../../testdata/configtest.json", true) - if err != nil { - log.Fatal(err) - } - - exchCfg, err := cfg.GetExchangeConfig("{{.CapitalName}}") - if err != nil { - log.Fatal(err) - } - - exchCfg.API.AuthenticatedSupport = true - {{ if .WS }} exchCfg.API.AuthenticatedWebsocketSupport = true {{ end }} - exchCfg.API.Credentials.Key = apiKey - exchCfg.API.Credentials.Secret = apiSecret - - err = {{.Variable}}.Setup(exchCfg) - if err != nil { - log.Fatal(err) - } - - os.Exit(m.Run()) -} - -// Ensures that this exchange package is compatible with IBotExchange -func TestInterface(t *testing.T) { - var e exchange.IBotExchange - if e = new({{.CapitalName}}); e == nil { - t.Fatal("unable to allocate exchange") - } -} - -func areTestAPIKeysSet() bool { - return {{.Variable}}.ValidateAPICredentials() -} - -// Implement tests for API endpoints below -{{end}} +{{define "test"}} +package {{.Name}} + +import ( + "log" + "os" + "testing" + + "github.com/thrasher-corp/gocryptotrader/config" + exchange "github.com/thrasher-corp/gocryptotrader/exchanges" +) + +// Please supply your own keys here to do authenticated endpoint testing +const ( + apiKey = "" + apiSecret = "" + canManipulateRealOrders = false +) + +var {{.Variable}} {{.CapitalName}} + +func TestMain(m *testing.M) { + {{.Variable}}.SetDefaults() + cfg := config.GetConfig() + err := cfg.LoadConfig("../../testdata/configtest.json", true) + if err != nil { + log.Fatal(err) + } + + exchCfg, err := cfg.GetExchangeConfig("{{.CapitalName}}") + if err != nil { + log.Fatal(err) + } + + exchCfg.API.AuthenticatedSupport = true + {{ if .WS }} exchCfg.API.AuthenticatedWebsocketSupport = true {{ end }} + exchCfg.API.Credentials.Key = apiKey + exchCfg.API.Credentials.Secret = apiSecret + + err = {{.Variable}}.Setup(exchCfg) + if err != nil { + log.Fatal(err) + } + + os.Exit(m.Run()) +} + +// Ensures that this exchange package is compatible with IBotExchange +func TestInterface(t *testing.T) { + var e exchange.IBotExchange + if e = new({{.CapitalName}}); e == nil { + t.Fatal("unable to allocate exchange") + } +} + +func areTestAPIKeysSet() bool { + return {{.Variable}}.ValidateAPICredentials() +} + +// Implement tests for API endpoints below +{{end}} diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl index 00df7ab3..935253ab 100644 --- a/cmd/exchange_template/wrapper_file.tmpl +++ b/cmd/exchange_template/wrapper_file.tmpl @@ -16,8 +16,9 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" - "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -323,8 +324,13 @@ func ({{.Variable}} *{{.CapitalName}}) GetFundingHistory() ([]exchange.FundHisto return nil, common.ErrNotYetImplemented } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func ({{.Variable}} *{{.CapitalName}}) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { +// GetRecentTrades returns the most recent trades for a currency and asset +func ({{.Variable}} *{{.CapitalName}}) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return nil, common.ErrNotYetImplemented +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func ({{.Variable}} *{{.CapitalName}}) GetHistoricTrades (p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { return nil, common.ErrNotYetImplemented } diff --git a/cmd/exchange_wrapper_coverage/main.go b/cmd/exchange_wrapper_coverage/main.go index fa7bd9ca..741be3a1 100644 --- a/cmd/exchange_wrapper_coverage/main.go +++ b/cmd/exchange_wrapper_coverage/main.go @@ -11,10 +11,11 @@ import ( "github.com/thrasher-corp/gocryptotrader/engine" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" ) const ( - totalWrappers = 20 + totalWrappers = 25 ) func main() { @@ -116,9 +117,14 @@ func testWrappers(e exchange.IBotExchange) []string { funcs = append(funcs, "GetAccountInfo") } - _, err = e.GetExchangeHistory(p, assetType, time.Time{}, time.Time{}) + _, err = e.GetRecentTrades(p, assetType) if err == common.ErrNotYetImplemented { - funcs = append(funcs, "GetExchangeHistory") + funcs = append(funcs, "GetRecentTrades") + } + + _, err = e.GetHistoricTrades(p, assetType, time.Time{}, time.Time{}) + if err == common.ErrNotYetImplemented { + funcs = append(funcs, "GetHistoricTrades") } _, err = e.GetFundingHistory() @@ -180,5 +186,25 @@ func testWrappers(e exchange.IBotExchange) []string { funcs = append(funcs, "WithdrawFiatFundsToInternationalBank") } + _, err = e.GetHistoricCandles(currency.Pair{}, asset.Spot, time.Unix(0, 0), time.Unix(0, 0), kline.OneDay) + if err == common.ErrNotYetImplemented { + funcs = append(funcs, "GetHistoricCandles") + } + + _, err = e.GetHistoricCandlesExtended(currency.Pair{}, asset.Spot, time.Unix(0, 0), time.Unix(0, 0), kline.OneDay) + if err == common.ErrNotYetImplemented { + funcs = append(funcs, "GetHistoricCandlesExtended") + } + + _, err = e.UpdateAccountInfo() + if err == common.ErrNotYetImplemented { + funcs = append(funcs, "UpdateAccountInfo") + } + + _, err = e.GetFeeByType(&exchange.FeeBuilder{}) + if err == common.ErrNotYetImplemented { + funcs = append(funcs, "GetFeeByType") + } + return funcs } diff --git a/cmd/exchange_wrapper_issues/main.go b/cmd/exchange_wrapper_issues/main.go index 04b77a86..f2137c62 100644 --- a/cmd/exchange_wrapper_issues/main.go +++ b/cmd/exchange_wrapper_issues/main.go @@ -26,6 +26,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/portfolio/banking" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -335,8 +336,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) log.Printf("Executing wrappers for %v %v %v", base.GetName(), assetTypes[i], p) if !authenticatedOnly { - var r1 *ticker.Price - r1, err = e.FetchTicker(p, assetTypes[i]) + var fetchTickerResponse *ticker.Price + fetchTickerResponse, err = e.FetchTicker(p, assetTypes[i]) msg = "" if err != nil { msg = err.Error() @@ -346,11 +347,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), Function: "FetchTicker", Error: msg, - Response: jsonifyInterface([]interface{}{r1}), + Response: jsonifyInterface([]interface{}{fetchTickerResponse}), }) - var r2 *ticker.Price - r2, err = e.UpdateTicker(p, assetTypes[i]) + var updateTickerResponse *ticker.Price + updateTickerResponse, err = e.UpdateTicker(p, assetTypes[i]) msg = "" if err != nil { msg = err.Error() @@ -360,11 +361,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), Function: "UpdateTicker", Error: msg, - Response: jsonifyInterface([]interface{}{r2}), + Response: jsonifyInterface([]interface{}{updateTickerResponse}), }) - var r3 *orderbook.Base - r3, err = e.FetchOrderbook(p, assetTypes[i]) + var fetchOrderbookResponse *orderbook.Base + fetchOrderbookResponse, err = e.FetchOrderbook(p, assetTypes[i]) msg = "" if err != nil { msg = err.Error() @@ -374,11 +375,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), Function: "FetchOrderbook", Error: msg, - Response: jsonifyInterface([]interface{}{r3}), + Response: jsonifyInterface([]interface{}{fetchOrderbookResponse}), }) - var r4 *orderbook.Base - r4, err = e.UpdateOrderbook(p, assetTypes[i]) + var updateOrderbookResponse *orderbook.Base + updateOrderbookResponse, err = e.UpdateOrderbook(p, assetTypes[i]) msg = "" if err != nil { msg = err.Error() @@ -388,11 +389,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), Function: "UpdateOrderbook", Error: msg, - Response: jsonifyInterface([]interface{}{r4}), + Response: jsonifyInterface([]interface{}{updateOrderbookResponse}), }) - var r5 []string - r5, err = e.FetchTradablePairs(assetTypes[i]) + var fetchTradablePairsResponse []string + fetchTradablePairsResponse, err = e.FetchTradablePairs(assetTypes[i]) msg = "" if err != nil { msg = err.Error() @@ -402,7 +403,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{assetTypes[i]}), Function: "FetchTradablePairs", Error: msg, - Response: jsonifyInterface([]interface{}{r5}), + Response: jsonifyInterface([]interface{}{fetchTradablePairsResponse}), }) // r6 err = e.UpdateTradablePairs(false) @@ -417,10 +418,67 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Error: msg, Response: jsonifyInterface([]interface{}{nil}), }) + + var getHistoricTradesResponse []trade.Data + getHistoricTradesResponse, err = e.GetHistoricTrades(p, assetTypes[i], time.Now().Add(-time.Hour*24), time.Now()) + msg = "" + if err != nil { + msg = err.Error() + responseContainer.ErrorCount++ + } + responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ + SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], time.Now().Add(-time.Hour * 24), time.Now()}), + Function: "GetHistoricTrades", + Error: msg, + Response: jsonifyInterface([]interface{}{getHistoricTradesResponse}), + }) + + var getRecentTradesResponse []trade.Data + getRecentTradesResponse, err = e.GetRecentTrades(p, assetTypes[i]) + msg = "" + if err != nil { + msg = err.Error() + responseContainer.ErrorCount++ + } + responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ + SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}), + Function: "GetRecentTrades", + Error: msg, + Response: jsonifyInterface([]interface{}{getRecentTradesResponse}), + }) + + var getHistoricCandlesResponse kline.Item + startTime, endTime := time.Now().AddDate(0, -1, 0), time.Now() + getHistoricCandlesResponse, err = e.GetHistoricCandles(p, assetTypes[i], startTime, endTime, kline.OneDay) + msg = "" + if err != nil { + msg = err.Error() + responseContainer.ErrorCount++ + } + responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ + Function: "GetHistoricCandles", + Error: msg, + Response: getHistoricCandlesResponse, + SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), + }) + + var getHisotirCandlesExtendedResponse kline.Item + getHisotirCandlesExtendedResponse, err = e.GetHistoricCandlesExtended(p, assetTypes[i], startTime, endTime, kline.OneDay) + msg = "" + if err != nil { + msg = err.Error() + responseContainer.ErrorCount++ + } + responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ + Function: "GetHistoricCandlesExtended", + Error: msg, + Response: getHisotirCandlesExtendedResponse, + SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), + }) } - var r7 account.Holdings - r7, err = e.FetchAccountInfo() + var fetchAccountInfoResponse account.Holdings + fetchAccountInfoResponse, err = e.FetchAccountInfo() msg = "" if err != nil { msg = err.Error() @@ -429,25 +487,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ Function: "FetchAccountInfo", Error: msg, - Response: jsonifyInterface([]interface{}{r7}), + Response: jsonifyInterface([]interface{}{fetchAccountInfoResponse}), }) - var r8 []exchange.TradeHistory - r8, err = e.GetExchangeHistory(p, assetTypes[i], time.Now().Add(-time.Minute), time.Now()) - msg = "" - if err != nil { - msg = err.Error() - responseContainer.ErrorCount++ - } - responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], time.Now().Add(-time.Minute), time.Now()}), - Function: "GetExchangeHistory", - Error: msg, - Response: jsonifyInterface([]interface{}{r8}), - }) - - var r9 []exchange.FundHistory - r9, err = e.GetFundingHistory() + var getFundingHistoryResponse []exchange.FundHistory + getFundingHistoryResponse, err = e.GetFundingHistory() msg = "" if err != nil { msg = err.Error() @@ -456,7 +500,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ Function: "GetFundingHistory", Error: msg, - Response: jsonifyInterface([]interface{}{r9}), + Response: jsonifyInterface([]interface{}{getFundingHistoryResponse}), }) feeType := exchange.FeeBuilder{ @@ -465,8 +509,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) PurchasePrice: config.OrderSubmission.Price, Amount: config.OrderSubmission.Amount, } - var r10 float64 - r10, err = e.GetFeeByType(&feeType) + var getFeeByTypeResponse float64 + getFeeByTypeResponse, err = e.GetFeeByType(&feeType) msg = "" if err != nil { msg = err.Error() @@ -476,7 +520,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{feeType}), Function: "GetFeeByType-Trade", Error: msg, - Response: jsonifyInterface([]interface{}{r10}), + Response: jsonifyInterface([]interface{}{getFeeByTypeResponse}), }) s := &order.Submit{ @@ -488,8 +532,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) ClientID: config.OrderSubmission.OrderID, AssetType: assetTypes[i], } - var r11 order.SubmitResponse - r11, err = e.SubmitOrder(s) + var submitOrderResponse order.SubmitResponse + submitOrderResponse, err = e.SubmitOrder(s) msg = "" if err != nil { msg = err.Error() @@ -499,7 +543,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{*s}), Function: "SubmitOrder", Error: msg, - Response: jsonifyInterface([]interface{}{r11}), + Response: jsonifyInterface([]interface{}{submitOrderResponse}), }) modifyRequest := order.Modify{ @@ -510,8 +554,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Price: config.OrderSubmission.Price, Amount: config.OrderSubmission.Amount, } - var r12 string - r12, err = e.ModifyOrder(&modifyRequest) + var modifyOrderResponse string + modifyOrderResponse, err = e.ModifyOrder(&modifyRequest) msg = "" if err != nil { msg = err.Error() @@ -521,9 +565,9 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{modifyRequest}), Function: "ModifyOrder", Error: msg, - Response: r12, + Response: modifyOrderResponse, }) - // r13 + cancelRequest := order.Cancel{ Side: testOrderSide, Pair: p, @@ -543,8 +587,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Response: jsonifyInterface([]interface{}{nil}), }) - var r14 order.CancelAllResponse - r14, err = e.CancelAllOrders(&cancelRequest) + var cancellAllOrdersResponse order.CancelAllResponse + cancellAllOrdersResponse, err = e.CancelAllOrders(&cancelRequest) msg = "" if err != nil { msg = err.Error() @@ -554,7 +598,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{cancelRequest}), Function: "CancelAllOrders", Error: msg, - Response: jsonifyInterface([]interface{}{r14}), + Response: jsonifyInterface([]interface{}{cancellAllOrdersResponse}), }) var r15 order.Detail @@ -576,8 +620,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Side: testOrderSide, Pairs: []currency.Pair{p}, } - var r16 []order.Detail - r16, err = e.GetOrderHistory(&historyRequest) + var getOrderHistoryResponse []order.Detail + getOrderHistoryResponse, err = e.GetOrderHistory(&historyRequest) msg = "" if err != nil { msg = err.Error() @@ -587,7 +631,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{historyRequest}), Function: "GetOrderHistory", Error: msg, - Response: jsonifyInterface([]interface{}{r16}), + Response: jsonifyInterface([]interface{}{getOrderHistoryResponse}), }) orderRequest := order.GetOrdersRequest{ @@ -595,8 +639,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) Side: testOrderSide, Pairs: []currency.Pair{p}, } - var r17 []order.Detail - r17, err = e.GetActiveOrders(&orderRequest) + var getActiveOrdersResponse []order.Detail + getActiveOrdersResponse, err = e.GetActiveOrders(&orderRequest) msg = "" if err != nil { msg = err.Error() @@ -606,11 +650,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{orderRequest}), Function: "GetActiveOrders", Error: msg, - Response: jsonifyInterface([]interface{}{r17}), + Response: jsonifyInterface([]interface{}{getActiveOrdersResponse}), }) - var r18 string - r18, err = e.GetDepositAddress(p.Base, "") + var getDepositAddressResponse string + getDepositAddressResponse, err = e.GetDepositAddress(p.Base, "") msg = "" if err != nil { msg = err.Error() @@ -620,7 +664,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{p.Base, ""}), Function: "GetDepositAddress", Error: msg, - Response: r18, + Response: getDepositAddressResponse, }) feeType = exchange.FeeBuilder{ @@ -629,8 +673,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) PurchasePrice: config.OrderSubmission.Price, Amount: config.OrderSubmission.Amount, } - var r19 float64 - r19, err = e.GetFeeByType(&feeType) + var GetFeeByTypeResponse float64 + GetFeeByTypeResponse, err = e.GetFeeByType(&feeType) msg = "" if err != nil { msg = err.Error() @@ -640,7 +684,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{feeType}), Function: "GetFeeByType-Crypto-Withdraw", Error: msg, - Response: jsonifyInterface([]interface{}{r19}), + Response: jsonifyInterface([]interface{}{GetFeeByTypeResponse}), }) withdrawRequest := withdraw.Request{ @@ -650,8 +694,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) }, Amount: config.OrderSubmission.Amount, } - var r20 *withdraw.ExchangeResponse - r20, err = e.WithdrawCryptocurrencyFunds(&withdrawRequest) + var withdrawCryptocurrencyFundsResponse *withdraw.ExchangeResponse + withdrawCryptocurrencyFundsResponse, err = e.WithdrawCryptocurrencyFunds(&withdrawRequest) msg = "" if err != nil { msg = err.Error() @@ -661,7 +705,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{withdrawRequest}), Function: "WithdrawCryptocurrencyFunds", Error: msg, - Response: r20, + Response: withdrawCryptocurrencyFundsResponse, }) feeType = exchange.FeeBuilder{ @@ -672,8 +716,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) FiatCurrency: currency.AUD, BankTransactionType: exchange.WireTransfer, } - var r21 float64 - r21, err = e.GetFeeByType(&feeType) + var getFeeByTypeFiatResponse float64 + getFeeByTypeFiatResponse, err = e.GetFeeByType(&feeType) msg = "" if err != nil { msg = err.Error() @@ -683,7 +727,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{feeType}), Function: "GetFeeByType-FIAT-Withdraw", Error: msg, - Response: jsonifyInterface([]interface{}{r21}), + Response: jsonifyInterface([]interface{}{getFeeByTypeFiatResponse}), }) withdrawRequestFiat := withdraw.Request{ @@ -716,8 +760,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) IntermediaryBankCode: config.BankDetails.IntermediaryBankCode, }, } - var r22 *withdraw.ExchangeResponse - r22, err = e.WithdrawFiatFunds(&withdrawRequestFiat) + var withdrawFiatFundsResponse *withdraw.ExchangeResponse + withdrawFiatFundsResponse, err = e.WithdrawFiatFunds(&withdrawRequestFiat) msg = "" if err != nil { msg = err.Error() @@ -727,11 +771,11 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{withdrawRequestFiat}), Function: "WithdrawFiatFunds", Error: msg, - Response: r22, + Response: withdrawFiatFundsResponse, }) - var r23 *withdraw.ExchangeResponse - r23, err = e.WithdrawFiatFundsToInternationalBank(&withdrawRequestFiat) + var withdrawFiatFundsInternationalResponse *withdraw.ExchangeResponse + withdrawFiatFundsInternationalResponse, err = e.WithdrawFiatFundsToInternationalBank(&withdrawRequestFiat) msg = "" if err != nil { msg = err.Error() @@ -741,39 +785,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) SentParams: jsonifyInterface([]interface{}{withdrawRequestFiat}), Function: "WithdrawFiatFundsToInternationalBank", Error: msg, - Response: r23, + Response: withdrawFiatFundsInternationalResponse, }) - - if !authenticatedOnly { - var r24 kline.Item - startTime, endTime := time.Now().AddDate(0, -1, 0), time.Now() - r24, err = e.GetHistoricCandles(p, assetTypes[i], startTime, endTime, kline.OneDay) - msg = "" - if err != nil { - msg = err.Error() - responseContainer.ErrorCount++ - } - responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - Function: "GetHistoricCandles", - Error: msg, - Response: r24, - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), - }) - - var r25 kline.Item - r25, err = e.GetHistoricCandlesExtended(p, assetTypes[i], startTime, endTime, kline.OneDay) - msg = "" - if err != nil { - msg = err.Error() - responseContainer.ErrorCount++ - } - responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{ - Function: "GetHistoricCandlesExtended", - Error: msg, - Response: r25, - SentParams: jsonifyInterface([]interface{}{p, assetTypes[i], startTime, endTime, kline.OneDay}), - }) - } response = append(response, responseContainer) } return response diff --git a/cmd/gctcli/commands.go b/cmd/gctcli/commands.go index 41c8dd3a..80f70240 100644 --- a/cmd/gctcli/commands.go +++ b/cmd/gctcli/commands.go @@ -551,17 +551,17 @@ func getTicker(c *cli.Context) error { return errInvalidAsset } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetTicker(context.Background(), &gctrpc.GetTickerRequest{ @@ -667,17 +667,17 @@ func getOrderbook(c *cli.Context) error { return errInvalidAsset } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetOrderbook(context.Background(), &gctrpc.GetOrderbookRequest{ @@ -938,12 +938,6 @@ func addPortfolioAddress(c *cli.Context) error { return cli.ShowCommandHelp(c, "addportfolioaddress") } - conn, err := setupClient() - if err != nil { - return err - } - defer conn.Close() - var address string var coinType string var description string @@ -968,7 +962,7 @@ func addPortfolioAddress(c *cli.Context) error { } else { description = c.Args().Get(2) } - + var err error if c.IsSet("balance") { balance = c.Float64("balance") } else if c.Args().Get(3) != "" { @@ -993,6 +987,12 @@ func addPortfolioAddress(c *cli.Context) error { supportedExchanges = c.Args().Get(5) } + conn, err := setupClient() + if err != nil { + return err + } + defer conn.Close() + client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.AddPortfolioAddress(context.Background(), &gctrpc.AddPortfolioAddressRequest{ @@ -1039,12 +1039,6 @@ func removePortfolioAddress(c *cli.Context) error { return cli.ShowCommandHelp(c, "removeportfolioaddress") } - conn, err := setupClient() - if err != nil { - return err - } - defer conn.Close() - var address string var coinType string var description string @@ -1067,6 +1061,12 @@ func removePortfolioAddress(c *cli.Context) error { description = c.Args().Get(2) } + conn, err := setupClient() + if err != nil { + return err + } + defer conn.Close() + client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.RemovePortfolioAddress(context.Background(), &gctrpc.RemovePortfolioAddressRequest{ @@ -1187,17 +1187,17 @@ func getOrders(c *cli.Context) error { return errInvalidPair } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{ Exchange: exchangeName, @@ -1438,17 +1438,17 @@ func submitOrder(c *cli.Context) error { return errInvalidAsset } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.SubmitOrder(context.Background(), &gctrpc.SubmitOrderRequest{ Exchange: exchangeName, @@ -1551,17 +1551,17 @@ func simulateOrder(c *cli.Context) error { return errors.New("amount must be set") } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.SimulateOrder(context.Background(), &gctrpc.SimulateOrderRequest{ Exchange: exchangeName, @@ -1656,17 +1656,17 @@ func whaleBomb(c *cli.Context) error { } } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.WhaleBomb(context.Background(), &gctrpc.WhaleBombRequest{ Exchange: exchangeName, @@ -2029,17 +2029,17 @@ func addEvent(c *cli.Context) error { return fmt.Errorf("action is required") } + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.AddEvent(context.Background(), &gctrpc.AddEventRequest{ Exchange: exchangeName, @@ -2673,19 +2673,15 @@ func withdrawlRequestByDate(c *cli.Context) error { if err != nil { return fmt.Errorf("invalid time format for start: %v", err) } - e, err := time.Parse(common.SimpleTimeFormat, endTime) if err != nil { return fmt.Errorf("invalid time format for end: %v", err) } if e.Before(s) { - return errors.New("start cannot be after before") + return errors.New("start cannot be after end") } - _, offset := time.Now().Zone() - loc := time.FixedZone("", -offset) - conn, err := setupClient() if err != nil { return err @@ -2696,8 +2692,8 @@ func withdrawlRequestByDate(c *cli.Context) error { result, err := client.WithdrawalEventsByDate(context.Background(), &gctrpc.WithdrawalEventsByDateRequest{ Exchange: exchange, - Start: s.In(loc).Format(common.SimpleTimeFormat), - End: e.In(loc).Format(common.SimpleTimeFormat), + Start: negateLocalOffset(s), + End: negateLocalOffset(e), Limit: int32(limit), }, ) @@ -2885,17 +2881,17 @@ func getOrderbookStream(c *cli.Context) error { return errInvalidAsset } + p, err := currency.NewPairDelimiter(pair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(pair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetOrderbookStream(context.Background(), &gctrpc.GetOrderbookStreamRequest{ @@ -3094,17 +3090,17 @@ func getTickerStream(c *cli.Context) error { return errInvalidAsset } + p, err := currency.NewPairDelimiter(pair, pairDelimiter) + if err != nil { + return err + } + conn, err := setupClient() if err != nil { return err } defer conn.Close() - p, err := currency.NewPairDelimiter(pair, pairDelimiter) - if err != nil { - return err - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetTickerStream(context.Background(), &gctrpc.GetTickerStreamRequest{ @@ -3288,7 +3284,7 @@ func getAuditEvent(c *cli.Context) error { } if e.Before(s) { - return errors.New("start cannot be after before") + return errors.New("start cannot be after end") } conn, err := setupClient() @@ -3300,16 +3296,12 @@ func getAuditEvent(c *cli.Context) error { client := gctrpc.NewGoCryptoTraderClient(conn) - _, offset := time.Now().Zone() - loc := time.FixedZone("", -offset) - result, err := client.GetAuditEvent(context.Background(), &gctrpc.GetAuditEventRequest{ - StartDate: s.In(loc).Format(common.SimpleTimeFormat), - EndDate: e.In(loc).Format(common.SimpleTimeFormat), + StartDate: negateLocalOffset(s), + EndDate: negateLocalOffset(e), Limit: int32(limit), OrderBy: order, - Offset: int32(offset), }) if err != nil { @@ -3788,6 +3780,10 @@ var getHistoricCandlesCommand = cli.Command{ Value: 86400, Destination: &candleGranularity, }, + cli.BoolFlag{ + Name: "fillmissingdatawithtrades, fill", + Usage: "will create candles for missing intervals using stored trade data ", + }, }, } @@ -3849,6 +3845,13 @@ func getHistoricCandles(c *cli.Context) error { } } + var fillMissingData bool + if c.IsSet("fillmissingdatawithtrades") { + fillMissingData = c.Bool("fillmissingdatawithtrades") + } else if c.IsSet("fill") { + fillMissingData = c.Bool("fill") + } + conn, err := setupClient() if err != nil { return err @@ -3857,8 +3860,8 @@ func getHistoricCandles(c *cli.Context) error { candleInterval := time.Duration(candleGranularity) * time.Second - end := time.Now().UTC().Truncate(candleInterval) - start := end.Add(-candleInterval * time.Duration(candleRangeSize)) + e := time.Now().Truncate(candleInterval) + s := e.Add(-candleInterval * time.Duration(candleRangeSize)) client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetHistoricCandles(context.Background(), @@ -3869,10 +3872,11 @@ func getHistoricCandles(c *cli.Context) error { Base: p.Base.String(), Quote: p.Quote.String(), }, - AssetType: assetType, - Start: start.Unix(), - End: end.Unix(), - TimeInterval: int64(candleInterval), + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + TimeInterval: int64(candleInterval), + FillMissingWithTrades: fillMissingData, }) if err != nil { return err @@ -3893,11 +3897,11 @@ var getHistoricCandlesExtendedCommand = cli.Command{ Usage: "the exchange to get the candles from", }, cli.StringFlag{ - Name: "pair", + Name: "pair, p", Usage: "the currency pair to get the candles for", }, cli.StringFlag{ - Name: "asset", + Name: "asset, a", Usage: "the asset type of the currency pair", }, cli.Int64Flag{ @@ -3922,10 +3926,18 @@ var getHistoricCandlesExtendedCommand = cli.Command{ Name: "sync", Usage: "", }, + cli.BoolFlag{ + Name: "force", + Usage: "will overwrite any conflicting candle data on save ", + }, cli.BoolFlag{ Name: "db", Usage: "source data from database ", }, + cli.BoolFlag{ + Name: "fillmissingdatawithtrades, fill", + Usage: "will create candles for missing intervals using stored trade data ", + }, }, } @@ -3996,9 +4008,40 @@ func getHistoricCandlesExtended(c *cli.Context) error { sync = c.Bool("sync") } - var db bool + var useDB bool if c.IsSet("db") { - db = c.Bool("db") + useDB = c.Bool("db") + } + + var fillMissingData bool + if c.IsSet("fillmissingdatawithtrades") { + fillMissingData = c.Bool("fillmissingdatawithtrades") + } else if c.IsSet("fill") { + fillMissingData = c.Bool("fill") + } + + var force bool + if c.IsSet("force") { + force = c.Bool("force") + } + + if force && !sync { + return errors.New("cannot forcefully overwrite without sync") + } + + candleInterval := time.Duration(candleGranularity) * time.Second + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + if e.Before(s) { + return errors.New("start cannot be after end") } conn, err := setupClient() @@ -4007,22 +4050,6 @@ func getHistoricCandlesExtended(c *cli.Context) error { } defer conn.Close() - candleInterval := time.Duration(candleGranularity) * time.Second - - s, err := time.Parse(common.SimpleTimeFormat, startTime) - if err != nil { - return fmt.Errorf("invalid time format for start: %v", err) - } - - e, err := time.Parse(common.SimpleTimeFormat, endTime) - if err != nil { - return fmt.Errorf("invalid time format for end: %v", err) - } - - if e.Before(s) { - return errors.New("start cannot be after before") - } - client := gctrpc.NewGoCryptoTraderClient(conn) result, err := client.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ @@ -4032,13 +4059,15 @@ func getHistoricCandlesExtended(c *cli.Context) error { Base: p.Base.String(), Quote: p.Quote.String(), }, - AssetType: assetType, - Start: s.Unix(), - End: e.Unix(), - TimeInterval: int64(candleInterval), - ExRequest: true, - Sync: sync, - UseDb: db, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + TimeInterval: int64(candleInterval), + ExRequest: true, + Sync: sync, + UseDb: useDB, + FillMissingWithTrades: fillMissingData, + Force: force, }) if err != nil { return err @@ -4047,3 +4076,167 @@ func getHistoricCandlesExtended(c *cli.Context) error { jsonOutput(result) return nil } + +var findMissingSavedCandleIntervalsCommand = cli.Command{ + Name: "findmissingsavedcandleintervals", + Usage: "will highlight any interval that is missing candle data so you can fill that gap", + ArgsUsage: " ", + Action: findMissingSavedCandleIntervals, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to find the missing candles", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + cli.Int64Flag{ + Name: "interval, i", + Usage: fmt.Sprintf(klineMessage, "interval"), + Value: 86400, + Destination: &candleGranularity, + }, + cli.StringFlag{ + Name: "start", + Usage: " rounded down to the nearest hour", + Value: time.Now().AddDate(0, -1, 0).Truncate(time.Hour).Format(common.SimpleTimeFormat), + Destination: &startTime, + }, + cli.StringFlag{ + Name: "end", + Usage: " rounded down to the nearest hour", + Value: time.Now().Truncate(time.Hour).Format(common.SimpleTimeFormat), + Destination: &endTime, + }, + }, +} + +func findMissingSavedCandleIntervals(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "findmissingsavedcandleintervals") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + if c.IsSet("interval") { + candleGranularity = c.Int64("interval") + } else if c.Args().Get(3) != "" { + candleGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64) + if err != nil { + return err + } + } + + if !c.IsSet("start") { + if c.Args().Get(4) != "" { + startTime = c.Args().Get(4) + } + } + + if !c.IsSet("end") { + if c.Args().Get(5) != "" { + endTime = c.Args().Get(5) + } + } + + candleInterval := time.Duration(candleGranularity) * time.Second + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + if e.Before(s) { + return errors.New("start cannot be after end") + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.FindMissingSavedCandleIntervals(context.Background(), + &gctrpc.FindMissingCandlePeriodsRequest{ + ExchangeName: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + Interval: int64(candleInterval), + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} + +// negateLocalOffset helps negate the offset of time generation +// when the unix time gets to rpcserver, it no longer is the same time +// that was sent as it handles it as a UTC value, even though when +// using starttime it is generated as your local time +// eg 2020-01-01 12:00:00 +10 will convert into +// 2020-01-01 12:00:00 +00 when at RPCServer +// so this function will minus the offset from the local sent time +// to allow for proper use at RPCServer +func negateLocalOffset(t time.Time) string { + _, offset := time.Now().Zone() + loc := time.FixedZone("", -offset) + + return t.In(loc).Format(common.SimpleTimeFormat) +} diff --git a/cmd/gctcli/main.go b/cmd/gctcli/main.go index a8b517c3..9e0e03e5 100644 --- a/cmd/gctcli/main.go +++ b/cmd/gctcli/main.go @@ -141,8 +141,10 @@ func main() { getAuditEventCommand, getHistoricCandlesCommand, getHistoricCandlesExtendedCommand, + findMissingSavedCandleIntervalsCommand, gctScriptCommand, websocketManagerCommand, + tradeCommand, } err := app.Run(os.Args) diff --git a/cmd/gctcli/trades.go b/cmd/gctcli/trades.go new file mode 100644 index 00000000..b6abede5 --- /dev/null +++ b/cmd/gctcli/trades.go @@ -0,0 +1,765 @@ +package main + +import ( + "context" + "errors" + "fmt" + "strconv" + "time" + + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/gctrpc" + "github.com/urfave/cli" +) + +var tradeCommand = cli.Command{ + Name: "trade", + Usage: "execute trade related commands", + ArgsUsage: " ", + Subcommands: []cli.Command{ + { + Name: "setexchangetradeprocessing", + Usage: "sets whether an exchange can save trades to the database", + ArgsUsage: " ", + Action: setExchangeTradeProcessing, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to change the status of", + }, + cli.BoolFlag{ + Name: "status", + Usage: "/", + }, + }, + }, + { + Name: "getrecent", + Usage: "gets recent trades", + ArgsUsage: " ", + Action: getRecentTrades, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to get the trades from", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair to get the trades for", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + }, + }, + { + Name: "gethistoric", + Usage: "gets trades between two periods", + ArgsUsage: " ", + Action: getHistoricTrades, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to get the trades from", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair to get the trades for", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + cli.StringFlag{ + Name: "start", + Usage: "", + Value: time.Now().Add(-time.Hour * 6).Format(common.SimpleTimeFormat), + Destination: &startTime, + }, + cli.StringFlag{ + Name: "end", + Usage: " WARNING: large date ranges may take considerable time", + Value: time.Now().Format(common.SimpleTimeFormat), + Destination: &endTime, + }, + }, + }, + { + Name: "getsaved", + Usage: "gets trades from the database", + ArgsUsage: " ", + Action: getSavedTrades, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to get the trades from", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair to get the trades for", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + cli.StringFlag{ + Name: "start", + Usage: "", + Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat), + Destination: &startTime, + }, + cli.StringFlag{ + Name: "end", + Usage: "", + Value: time.Now().Format(common.SimpleTimeFormat), + Destination: &endTime, + }, + }, + }, + { + Name: "findmissingsavedtradeintervals", + Usage: "will highlight any interval that is missing trade data so you can fill that gap", + ArgsUsage: " ", + Action: findMissingSavedTradeIntervals, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange to find the missing trades", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + cli.StringFlag{ + Name: "start", + Usage: " rounded down to the nearest hour", + Value: time.Now().Add(-time.Hour * 24).Truncate(time.Hour).Format(common.SimpleTimeFormat), + Destination: &startTime, + }, + cli.StringFlag{ + Name: "end", + Usage: " rounded down to the nearest hour", + Value: time.Now().Truncate(time.Hour).Format(common.SimpleTimeFormat), + Destination: &endTime, + }, + }, + }, + { + Name: "convertsavedtradestocandles", + Usage: "explicitly converts stored trade data to candles and saves the result to the database", + ArgsUsage: " ", + Action: convertSavedTradesToCandles, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "exchange, e", + Usage: "the exchange", + }, + cli.StringFlag{ + Name: "pair, p", + Usage: "the currency pair to get the trades for", + }, + cli.StringFlag{ + Name: "asset, a", + Usage: "the asset type of the currency pair", + }, + cli.Int64Flag{ + Name: "interval, i", + Usage: fmt.Sprintf(klineMessage, "interval"), + Value: 86400, + Destination: &candleGranularity, + }, + cli.StringFlag{ + Name: "start", + Usage: "", + Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat), + Destination: &startTime, + }, + cli.StringFlag{ + Name: "end", + Usage: "", + Value: time.Now().Format(common.SimpleTimeFormat), + Destination: &endTime, + }, + cli.BoolFlag{ + Name: "sync, s", + Usage: "will sync the resulting candles to the database ", + }, + cli.BoolFlag{ + Name: "force, f", + Usage: "will overwrite any conflicting candle data on save ", + }, + }, + }, + }, +} + +func findMissingSavedTradeIntervals(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "findmissingsavedtradeintervals") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + if !c.IsSet("start") { + if c.Args().Get(3) != "" { + startTime = c.Args().Get(3) + } + } + + if !c.IsSet("end") { + if c.Args().Get(4) != "" { + endTime = c.Args().Get(4) + } + } + + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.FindMissingSavedTradeIntervals(context.Background(), + &gctrpc.FindMissingTradePeriodsRequest{ + ExchangeName: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} + +func setExchangeTradeProcessing(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "setexchangetradeprocessing") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var status bool + if c.IsSet("status") { + status = c.Bool("status") + } else { + statusStr := c.Args().Get(1) + var err error + status, err = strconv.ParseBool(statusStr) + if err != nil { + return err + } + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.SetExchangeTradeProcessing(context.Background(), + &gctrpc.SetExchangeTradeProcessingRequest{ + Exchange: exchangeName, + Status: status, + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} + +func getSavedTrades(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "getsaved") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + if !c.IsSet("start") { + if c.Args().Get(3) != "" { + startTime = c.Args().Get(3) + } + } + + if !c.IsSet("end") { + if c.Args().Get(4) != "" { + endTime = c.Args().Get(4) + } + } + + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + if e.Before(s) { + return errors.New("start cannot be after end") + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.GetSavedTrades(context.Background(), + &gctrpc.GetSavedTradesRequest{ + Exchange: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} + +func getRecentTrades(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "getrecent") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.GetRecentTrades(context.Background(), + &gctrpc.GetSavedTradesRequest{ + Exchange: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} + +func getHistoricTrades(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "gethistoric") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + if !c.IsSet("start") { + if c.Args().Get(3) != "" { + startTime = c.Args().Get(3) + } + } + + if !c.IsSet("end") { + if c.Args().Get(4) != "" { + endTime = c.Args().Get(4) + } + } + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + if e.Before(s) { + return errors.New("start cannot be after end") + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + streamStartTime := time.Now() + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.GetHistoricTrades(context.Background(), + &gctrpc.GetSavedTradesRequest{ + Exchange: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + }) + if err != nil { + return err + } + fmt.Printf("%v\t| Beginning stream retrieving trades in 1 hour batches from %v to %v\n", + time.Now().Format(time.Kitchen), + s.UTC().Format(common.SimpleTimeFormatWithTimezone), + e.UTC().Format(common.SimpleTimeFormatWithTimezone)) + fmt.Printf("%v\t| If you have provided a large time range, please be patient\n\n", + time.Now().Format(time.Kitchen)) + for { + resp, err := result.Recv() + if err != nil { + return err + } + if len(resp.Trades) == 0 { + break + } + fmt.Printf("%v\t| Processed %v trades between %v and %v\n", + time.Now().Format(time.Kitchen), + len(resp.Trades), + resp.Trades[0].Timestamp, + resp.Trades[len(resp.Trades)-1].Timestamp) + } + + fmt.Printf("%v\t| Trade retrieval complete! Process took %v\n", + time.Now().Format(time.Kitchen), + time.Since(streamStartTime)) + + return nil +} + +func convertSavedTradesToCandles(c *cli.Context) error { + if c.NArg() == 0 && c.NumFlags() == 0 { + return cli.ShowCommandHelp(c, "convertsavedtradestocandles") + } + + var exchangeName string + if c.IsSet("exchange") { + exchangeName = c.String("exchange") + } else { + exchangeName = c.Args().First() + } + if !validExchange(exchangeName) { + return errInvalidExchange + } + + var currencyPair string + if c.IsSet("pair") { + currencyPair = c.String("pair") + } else { + currencyPair = c.Args().Get(1) + } + if !validPair(currencyPair) { + return errInvalidPair + } + + p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter) + if err != nil { + return err + } + + var assetType string + if c.IsSet("asset") { + assetType = c.String("asset") + } else { + assetType = c.Args().Get(2) + } + + if !validAsset(assetType) { + return errInvalidAsset + } + + if c.IsSet("interval") { + candleGranularity = c.Int64("interval") + } else if c.Args().Get(3) != "" { + candleGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64) + if err != nil { + return err + } + } + + if !c.IsSet("start") { + if c.Args().Get(4) != "" { + startTime = c.Args().Get(4) + } + } + + if !c.IsSet("end") { + if c.Args().Get(5) != "" { + endTime = c.Args().Get(5) + } + } + + var sync bool + if c.IsSet("sync") { + sync = c.Bool("sync") + } + + var force bool + if c.IsSet("force") { + force = c.Bool("force") + } + + if force && !sync { + return errors.New("cannot forcefully overwrite without sync") + } + + candleInterval := time.Duration(candleGranularity) * time.Second + var s, e time.Time + s, err = time.Parse(common.SimpleTimeFormat, startTime) + if err != nil { + return fmt.Errorf("invalid time format for start: %v", err) + } + e, err = time.Parse(common.SimpleTimeFormat, endTime) + if err != nil { + return fmt.Errorf("invalid time format for end: %v", err) + } + + if e.Before(s) { + return errors.New("start cannot be after end") + } + + conn, err := setupClient() + if err != nil { + return err + } + defer func() { + err = conn.Close() + if err != nil { + fmt.Print(err) + } + }() + + client := gctrpc.NewGoCryptoTraderClient(conn) + result, err := client.ConvertTradesToCandles(context.Background(), + &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: exchangeName, + Pair: &gctrpc.CurrencyPair{ + Delimiter: p.Delimiter, + Base: p.Base.String(), + Quote: p.Quote.String(), + }, + AssetType: assetType, + Start: negateLocalOffset(s), + End: negateLocalOffset(e), + TimeInterval: int64(candleInterval), + Sync: sync, + Force: force, + }) + if err != nil { + return err + } + + jsonOutput(result) + return nil +} diff --git a/common/common.go b/common/common.go index 5c7f8a8c..2bc4dc7b 100644 --- a/common/common.go +++ b/common/common.go @@ -42,7 +42,10 @@ const ( ) // SimpleTimeFormat a common, but non-implemented time format in golang -const SimpleTimeFormat = "2006-01-02 15:04:05" +const ( + SimpleTimeFormat = "2006-01-02 15:04:05" + SimpleTimeFormatWithTimezone = "2006-01-02 15:04:05 MST" +) func initialiseHTTPClient() { // If the HTTPClient isn't set, start a new client with a default timeout of 15 seconds diff --git a/common/timeperiods/timeperiods.go b/common/timeperiods/timeperiods.go new file mode 100644 index 00000000..2879fb24 --- /dev/null +++ b/common/timeperiods/timeperiods.go @@ -0,0 +1,148 @@ +package timeperiods + +import ( + "errors" + "sort" + "time" + + "github.com/thrasher-corp/gocryptotrader/common" +) + +// FindTimeRangesContainingData will break the start and end into time periods using the provided period +// it will then check whether any comparisonTimes are within those periods and concatenate them +// eg if no comparisonTimes match, you will receive 1 TimeRange of Start End with dataInRange = false +// eg2 if 1 comparisonTime matches in the middle of start and end, you will receive three ranges +func FindTimeRangesContainingData(start, end time.Time, period time.Duration, comparisonTimes []time.Time) ([]TimeRange, error) { + var errs common.Errors + if start.IsZero() { + errs = append(errs, errors.New("invalid start time")) + } + if end.IsZero() { + errs = append(errs, errors.New("invalid end time")) + } + if err := validatePeriod(period); err != nil { + errs = append(errs, err) + } + if len(errs) > 0 { + return nil, errs + } + var t TimePeriodCalculator + t.periodDuration = period + t.start = start.Truncate(period) + t.end = end.Truncate(period) + t.comparisonTimes = comparisonTimes + + t.setTimePeriodExists() + t.Sort(false) + t.calculateRanges() + + return t.TimeRanges, nil +} + +func validatePeriod(period time.Duration) error { + if period != time.Hour && + period != time.Second && + period != time.Minute && + period != time.Hour*24 { + return errors.New("invalid period") + } + return nil +} + +// CalculateTimePeriodsInRange can break down start and end times into time periods +// eg 1 hourly intervals +func CalculateTimePeriodsInRange(start, end time.Time, period time.Duration) ([]TimePeriod, error) { + var errs common.Errors + if start.IsZero() { + errs = append(errs, errors.New("invalid start time")) + } + if end.IsZero() { + errs = append(errs, errors.New("invalid end time")) + } + if err := validatePeriod(period); err != nil { + errs = append(errs, err) + } + if len(errs) > 0 { + return nil, errs + } + + var t TimePeriodCalculator + t.periodDuration = period + t.start = start.Truncate(period) + t.end = end.Truncate(period) + + t.calculatePeriods() + + return t.TimePeriods, nil +} + +func (t *TimePeriodCalculator) calculateRanges() { + var tr TimeRange + for i := range t.TimePeriods { + if i != 0 { + if (t.TimePeriods[i].dataInRange && !t.TimePeriods[i-1].dataInRange) || + (!t.TimePeriods[i].dataInRange && t.TimePeriods[i-1].dataInRange) { + // the status has changed and therefore a range has ended + tr.HasDataInRange = t.TimePeriods[i-1].dataInRange + tr.EndOfRange = t.TimePeriods[i].Time + t.TimeRanges = append(t.TimeRanges, tr) + tr = TimeRange{} + } + } + if tr.StartOfRange.IsZero() { + // start of new time range + tr.StartOfRange = t.TimePeriods[i].Time + } + } + if !tr.StartOfRange.IsZero() { + if tr.EndOfRange.IsZero() { + tr.EndOfRange = t.end + } + tr.HasDataInRange = t.TimePeriods[len(t.TimePeriods)-1].dataInRange + t.TimeRanges = append(t.TimeRanges, tr) + tr = TimeRange{} + } +} + +func (t *TimePeriodCalculator) calculatePeriods() { + if t.start.IsZero() || t.end.IsZero() { + return + } + if t.start.After(t.end) { + return + } + iterateDateMate := t.start + for !iterateDateMate.Equal(t.end) && !iterateDateMate.After(t.end) { + tp := TimePeriod{ + Time: iterateDateMate, + dataInRange: false, + } + t.TimePeriods = append(t.TimePeriods, tp) + iterateDateMate = iterateDateMate.Add(t.periodDuration) + } +} + +// setTimePeriodExists compares loaded comparisonTimes +// against calculated TimePeriods to determine whether +// there is existing data within the time period +func (t *TimePeriodCalculator) setTimePeriodExists() { + t.calculatePeriods() + for i := range t.TimePeriods { + for j := range t.comparisonTimes { + if t.comparisonTimes[j].Truncate(t.periodDuration).Equal(t.TimePeriods[i].Time) { + t.TimePeriods[i].dataInRange = true + break + } + } + } +} + +// Sort will sort the time period asc or desc +func (t *TimePeriodCalculator) Sort(desc bool) { + sort.Slice(t.TimePeriods, func(i, j int) bool { + if desc { + return t.TimePeriods[i].Time.After(t.TimePeriods[j].Time) + } + return t.TimePeriods[i].Time.Before(t.TimePeriods[j].Time) + }) +} diff --git a/common/timeperiods/timeperiods_test.go b/common/timeperiods/timeperiods_test.go new file mode 100644 index 00000000..7c9e2b4c --- /dev/null +++ b/common/timeperiods/timeperiods_test.go @@ -0,0 +1,188 @@ +package timeperiods + +import ( + "testing" + "time" +) + +func TestFindTimeRangesContainingData(t *testing.T) { + // validation issues + _, err := FindTimeRangesContainingData( + time.Time{}, + time.Time{}, + 0, + nil, + ) + if err != nil && err.Error() != "invalid start time, invalid end time, invalid period" { + t.Fatal(err) + } + // empty trade times + searchStartTime := time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC) + searchEndTime := time.Date(2020, 1, 1, 10, 0, 0, 0, time.UTC) + var tradeTimes []time.Time + var ranges []TimeRange + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 1 { + t.Errorf("expected 1 time range, received %v", len(ranges)) + } + // 1 trade with 3 periods + tradeTimes = append(tradeTimes, time.Date(2020, 1, 1, 2, 0, 0, 0, time.UTC)) + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 3 { + t.Errorf("expected 3 time ranges, received %v", len(ranges)) + } + // 2 trades with 3 periods + tradeTimes = append(tradeTimes, time.Date(2020, 1, 1, 3, 0, 0, 0, time.UTC)) + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 3 { + t.Errorf("expected 3 time ranges, received %v", len(ranges)) + } + // 3 trades with 5 periods + tradeTimes = append(tradeTimes, time.Date(2020, 1, 1, 5, 0, 0, 0, time.UTC)) + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 5 { + t.Errorf("expected 5 time ranges, received %v", len(ranges)) + } + // 4 trades with 5 periods + tradeTimes = append(tradeTimes, time.Date(2020, 1, 1, 6, 0, 0, 0, time.UTC)) + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 5 { + t.Errorf("expected 5 time ranges, received %v", len(ranges)) + } + // 5 trades with 6 periods + tradeTimes = append(tradeTimes, time.Date(2020, 1, 1, 9, 0, 0, 0, time.UTC)) + ranges, err = FindTimeRangesContainingData( + searchStartTime, + searchEndTime, + time.Hour, + tradeTimes, + ) + if err != nil { + t.Error(err) + } + if len(ranges) != 6 { + t.Errorf("expected 6 time ranges, received %v", len(ranges)) + } +} + +func TestCalculateTimePeriodsInRange(t *testing.T) { + // validation issues + _, err := CalculateTimePeriodsInRange(time.Time{}, time.Time{}, 0) + if err != nil && err.Error() != "invalid start time, invalid end time, invalid period" { + t.Fatal(err) + } + // start after end + var intervals []TimePeriod + timeStart := time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC) + timeEnd := time.Date(2020, 1, 2, 1, 0, 0, 0, time.UTC) + intervals, err = CalculateTimePeriodsInRange(timeEnd, timeStart, time.Hour) + if err != nil { + t.Error(err) + } + if len(intervals) != 0 { + t.Errorf("expected 0 interval(s), received %v", len(intervals)) + } + // 1 interval + intervals, err = CalculateTimePeriodsInRange(timeStart, timeStart.Add(time.Hour), time.Hour) + if err != nil { + t.Error(err) + } + if len(intervals) != 1 { + t.Errorf("expected 1 interval(s), received %v", len(intervals)) + } + // multiple intervals + intervals, err = CalculateTimePeriodsInRange(timeStart, timeEnd, time.Hour) + if err != nil { + t.Error(err) + } + if len(intervals) != 24 { + t.Errorf("expected 24 interval(s), received %v", len(intervals)) + } + // odd time + intervals, err = CalculateTimePeriodsInRange(timeStart.Add(-time.Minute*30), timeEnd, time.Hour) + if err != nil { + t.Error(err) + } + if len(intervals) != 25 { + t.Errorf("expected 25 interval(s), received %v", len(intervals)) + } + // truncate always goes to zero, no mid rounding + intervals, err = CalculateTimePeriodsInRange(timeStart, timeStart.Add(time.Minute), time.Hour) + if err != nil { + t.Error(err) + } + if len(intervals) != 0 { + t.Errorf("expected 0 interval(s), received %v", len(intervals)) + } +} + +func TestValidateCalculatePeriods(t *testing.T) { + var tpc TimePeriodCalculator + tpc.calculatePeriods() + if len(tpc.TimePeriods) > 0 { + t.Error("validation has been removed") + } +} + +func TestSort(t *testing.T) { + var tpc TimePeriodCalculator + date1 := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC) + date2 := time.Date(1901, 1, 1, 1, 1, 1, 1, time.UTC) + tpc.TimePeriods = append(tpc.TimePeriods, + TimePeriod{ + Time: date1, + }, + TimePeriod{ + Time: date2, + }, + ) + tpc.Sort(false) + if !tpc.TimePeriods[0].Time.Equal(date2) { + t.Errorf("expected %v, received %v", date2, tpc.TimePeriods[0].Time) + } + + tpc.Sort(true) + if !tpc.TimePeriods[0].Time.Equal(date1) { + t.Errorf("expected %v, received %v", date1, tpc.TimePeriods[0].Time) + } +} diff --git a/common/timeperiods/timeperiods_types.go b/common/timeperiods/timeperiods_types.go new file mode 100644 index 00000000..accc68b5 --- /dev/null +++ b/common/timeperiods/timeperiods_types.go @@ -0,0 +1,32 @@ +package timeperiods + +import ( + "time" +) + +// TimePeriodCalculator is able analyse +// a time span and either break them down into +// chunks, or determine ranges that contain data or not +type TimePeriodCalculator struct { + start time.Time + end time.Time + comparisonTimes []time.Time + TimePeriods []TimePeriod + periodDuration time.Duration + TimeRanges []TimeRange +} + +// TimePeriod is a basic type which will know +// whether a period in time contains data +type TimePeriod struct { + Time time.Time + dataInRange bool +} + +// TimeRange holds a start and end dat range +// and whether that range contains data +type TimeRange struct { + StartOfRange time.Time + EndOfRange time.Time + HasDataInRange bool +} diff --git a/communications/smtpservice/smtpservice.go b/communications/smtpservice/smtpservice.go index 3cea3c7a..c4c4cfa4 100644 --- a/communications/smtpservice/smtpservice.go +++ b/communications/smtpservice/smtpservice.go @@ -64,6 +64,13 @@ func (s *SMTPservice) Send(subject, msg string) error { if subject == "" || msg == "" { return errors.New("STMPservice Send() please add subject and alert") } + if s.Host == "" || + s.Port == "" || + s.AccountName == "" || + s.AccountPassword == "" || + s.From == "" { + return errors.New("STMPservice Send() cannot send with unset service properties") + } log.Debugf(log.CommunicationMgr, "SMTP: Sending email to %v. Subject: %s Message: %s [From: %s]\n", s.RecipientList, subject, msg, s.From) diff --git a/config/config_types.go b/config/config_types.go index d527fcc2..91a9bebb 100644 --- a/config/config_types.go +++ b/config/config_types.go @@ -333,6 +333,7 @@ type FeaturesSupportedConfig struct { type FeaturesEnabledConfig struct { AutoPairUpdates bool `json:"autoPairUpdates"` Websocket bool `json:"websocketAPI"` + SaveTradeData bool `json:"saveTradeData"` } // FeaturesConfig stores the exchanges supported and enabled features diff --git a/currency/pair.go b/currency/pair.go index ccc9e985..16cfe983 100644 --- a/currency/pair.go +++ b/currency/pair.go @@ -107,3 +107,25 @@ func NewPairFromFormattedPairs(currencyPair string, pairs Pairs, pairFmt PairFor } return NewPairFromString(currencyPair) } + +// MatchPairsWithNoDelimiter will move along a predictable index on the provided currencyPair +// it will then split on that index and verify whether that currencypair exists in the +// supplied pairs +// this allows for us to match strange currencies with no delimiter where it is difficult to +// infer where the delimiter is located eg BETHERETH is BETHER ETH +func MatchPairsWithNoDelimiter(currencyPair string, pairs Pairs, pairFmt PairFormat) (Pair, error) { + for i := range pairs { + fPair := pairs[i].Format(pairFmt.Delimiter, pairFmt.Uppercase) + maxLen := 6 + if len(currencyPair) < maxLen { + maxLen = len(currencyPair) + } + for j := 1; j <= maxLen; j++ { + if fPair.Base.String() == currencyPair[0:j] && + fPair.Quote.String() == currencyPair[j:] { + return fPair, nil + } + } + } + return Pair{}, fmt.Errorf("currency %v not found in supplied pairs", currencyPair) +} diff --git a/currency/pair_test.go b/currency/pair_test.go index 14037172..defd383a 100644 --- a/currency/pair_test.go +++ b/currency/pair_test.go @@ -693,3 +693,86 @@ func TestIsInvalid(t *testing.T) { t.Error("IsInvalid() error expect true but received false") } } + +func TestMatchPairsWithNoDelimiter(t *testing.T) { + p1, err := NewPairDelimiter("BTC-USDT", "-") + if err != nil { + t.Fatal(err) + } + p2, err := NewPairDelimiter("LTC-USD", "-") + if err != nil { + t.Fatal(err) + } + p3, err := NewPairFromStrings("EQUAD", "BTC") + if err != nil { + t.Fatal(err) + } + p4, err := NewPairFromStrings("HTDF", "USDT") + if err != nil { + t.Fatal(err) + } + p5, err := NewPairFromStrings("BETHER", "ETH") + if err != nil { + t.Fatal(err) + } + pairs := Pairs{ + p1, + p2, + p3, + p4, + p5, + } + + p, err := MatchPairsWithNoDelimiter("BTCUSDT", pairs, PairFormat{ + Uppercase: true, + }) + if err != nil { + t.Fatal(err) + } + if p.Quote.String() != "USDT" && p.Base.String() != "BTC" { + t.Error("unexpected response") + } + + p, err = MatchPairsWithNoDelimiter("EQUADBTC", pairs, PairFormat{ + Uppercase: true, + }) + if err != nil { + t.Fatal(err) + } + if p.Base.String() != "EQUAD" && p.Quote.String() != "BTC" { + t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String()) + } + + p, err = MatchPairsWithNoDelimiter("EQUADBTC", pairs, PairFormat{ + Uppercase: true, + Delimiter: "/", + }) + if err != nil { + t.Fatal(err) + } + if p.Base.String() != "EQUAD" && p.Quote.String() != "BTC" { + t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String()) + } + + p, err = MatchPairsWithNoDelimiter("HTDFUSDT", pairs, PairFormat{ + Uppercase: true, + Delimiter: "/", + }) + if err != nil { + t.Fatal(err) + } + if p.Base.String() != "HTDF" && p.Quote.String() != "USDT" { + t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String()) + } + + p, err = MatchPairsWithNoDelimiter("BETHERETH", pairs, PairFormat{ + Uppercase: true, + Delimiter: "/", + }) + if err != nil { + t.Fatal(err) + } + if p.Base.String() != "BETHER" && p.Quote.String() != "ETH" { + t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String()) + } +} diff --git a/database/migrations/20200909083123_trade/postgres.sql b/database/migrations/20200909083123_trade/postgres.sql new file mode 100644 index 00000000..a795df71 --- /dev/null +++ b/database/migrations/20200909083123_trade/postgres.sql @@ -0,0 +1,20 @@ +-- +goose Up +CREATE TABLE IF NOT EXISTS trade +( + id uuid PRIMARY KEY DEFAULT gen_random_uuid(), + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid varchar, + base varchar(30) NOT NULL, + quote varchar(30) NOT NULL, + asset varchar NOT NULL, + price DOUBLE PRECISION NOT NULL, + amount DOUBLE PRECISION NOT NULL, + side varchar NOT NULL, + timestamp TIMESTAMPTZ NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid), + CONSTRAINT uniquetrade + unique(exchange_name_id, base, quote, asset, price, amount, side, timestamp) +); +-- +goose Down +DROP TABLE trade; \ No newline at end of file diff --git a/database/migrations/20200909083123_trade/sqlite3.sql b/database/migrations/20200909083123_trade/sqlite3.sql new file mode 100644 index 00000000..84f94717 --- /dev/null +++ b/database/migrations/20200909083123_trade/sqlite3.sql @@ -0,0 +1,20 @@ +-- +goose Up +CREATE TABLE IF NOT EXISTS trade +( + id text not null primary key, + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid TEXT, + base text NOT NULL, + quote text NOT NULL, + asset TEXT NOT NULL, + price REAL NOT NULL, + amount REAL NOT NULL, + side TEXT NOT NULL, + timestamp TIMESTAMP NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid) ON CONFLICT IGNORE, + CONSTRAINT uniquetrade + unique(exchange_name_id, base, quote, asset, price, amount, side, timestamp) ON CONFLICT IGNORE +); +-- +goose Down +DROP TABLE trade; diff --git a/database/migrations/20201013122046_ammend_trade_constraints/postgres.sql b/database/migrations/20201013122046_ammend_trade_constraints/postgres.sql new file mode 100644 index 00000000..98532f69 --- /dev/null +++ b/database/migrations/20201013122046_ammend_trade_constraints/postgres.sql @@ -0,0 +1,14 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE trade DROP CONSTRAINT uniquetrade; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,side, timestamp) + WHERE tid IS NULL; +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +DROP INDEX unique_trade_no_id; + +ALTER TABLE trade ADD CONSTRAINT uniquetrade + unique(exchange_name_id, base, quote, asset, price, amount, side, timestamp); +-- +goose StatementEnd diff --git a/database/migrations/20201013122046_ammend_trade_constraints/sqlite3.sql b/database/migrations/20201013122046_ammend_trade_constraints/sqlite3.sql new file mode 100644 index 00000000..30231da1 --- /dev/null +++ b/database/migrations/20201013122046_ammend_trade_constraints/sqlite3.sql @@ -0,0 +1,47 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE "trade_new" ( + id text not null primary key, + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid TEXT, + base text NOT NULL, + quote text NOT NULL, + asset TEXT NOT NULL, + price REAL NOT NULL, + amount REAL NOT NULL, + side TEXT NOT NULL, + timestamp TIMESTAMP NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid) ON CONFLICT IGNORE +); + +INSERT INTO trade_new SELECT id, exchange_name_id, tid, base, quote, asset, price, amount, side, timestamp FROM trade; +DROP TABLE trade; +ALTER TABLE trade_new RENAME TO trade; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,side, timestamp) + WHERE tid IS NULL; +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +CREATE TABLE "trade_new" ( + id text not null primary key, + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid TEXT, + base text NOT NULL, + quote text NOT NULL, + asset TEXT NOT NULL, + price REAL NOT NULL, + amount REAL NOT NULL, + side TEXT NOT NULL, + timestamp TIMESTAMP NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid) ON CONFLICT IGNORE, + CONSTRAINT uniquetrade + unique(exchange_name_id, base, quote, asset, price, amount, side, timestamp) ON CONFLICT IGNORE +); + +INSERT INTO trade_new SELECT id, exchange_name_id, tid, base, quote, asset, price, amount, side, timestamp FROM trade; +DROP TABLE trade; +ALTER TABLE trade_new RENAME TO trade; +-- +goose StatementEnd diff --git a/database/migrations/20201013151813_trade_nullable_sides/postgres.sql b/database/migrations/20201013151813_trade_nullable_sides/postgres.sql new file mode 100644 index 00000000..74797fc6 --- /dev/null +++ b/database/migrations/20201013151813_trade_nullable_sides/postgres.sql @@ -0,0 +1,23 @@ +-- +goose Up +-- +goose StatementBegin + +ALTER TABLE trade ALTER COLUMN side DROP NOT NULL; + +DROP INDEX unique_trade_no_id; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,timestamp) + WHERE tid IS NULL; + +UPDATE TRADE set side = null where side = 'UNKNOWN'; +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +UPDATE TRADE set side = '' where side IS NULL; + +ALTER TABLE trade ALTER COLUMN side SET NOT NULL; + +DROP INDEX unique_trade_no_id; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,side,timestamp) + WHERE tid IS NULL; +-- +goose StatementEnd diff --git a/database/migrations/20201013151813_trade_nullable_sides/sqlite3.sql b/database/migrations/20201013151813_trade_nullable_sides/sqlite3.sql new file mode 100644 index 00000000..26311ad3 --- /dev/null +++ b/database/migrations/20201013151813_trade_nullable_sides/sqlite3.sql @@ -0,0 +1,55 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE "trade_new" ( + id text not null primary key, + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid TEXT, + base text NOT NULL, + quote text NOT NULL, + asset TEXT NOT NULL, + price REAL NOT NULL, + amount REAL NOT NULL, + side TEXT, + timestamp TIMESTAMP NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid) ON CONFLICT IGNORE +); +INSERT INTO trade_new SELECT id, exchange_name_id, tid, base, quote, asset, price, amount, side, timestamp FROM trade; + +DROP TABLE trade; + +ALTER TABLE trade_new RENAME TO trade; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,timestamp) + WHERE tid IS NULL; + +UPDATE trade SET side = null WHERE side = 'UNKNOWN' OR side = ''; + +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +CREATE TABLE "trade_new" ( + id text not null primary key, + exchange_name_id uuid REFERENCES exchange(id) NOT NULL, + tid TEXT, + base text NOT NULL, + quote text NOT NULL, + asset TEXT NOT NULL, + price REAL NOT NULL, + amount REAL NOT NULL, + side TEXT NOT NULL, + timestamp TIMESTAMP NOT NULL, + CONSTRAINT uniquetradeid + unique(exchange_name_id, tid) ON CONFLICT IGNORE +); +UPDATE trade SET side = '' WHERE side IS NULL; + +INSERT INTO trade_new SELECT id, exchange_name_id, tid, base, quote, asset, price, amount, side, timestamp FROM trade; + +DROP TABLE trade; + +ALTER TABLE trade_new RENAME TO trade; + +CREATE UNIQUE INDEX unique_trade_no_id ON trade (base,quote,asset,price,amount,side,timestamp) + WHERE tid IS NULL; +-- +goose StatementEnd diff --git a/database/models/postgres/boil_table_names.go b/database/models/postgres/boil_table_names.go index bad4329f..acca258e 100644 --- a/database/models/postgres/boil_table_names.go +++ b/database/models/postgres/boil_table_names.go @@ -9,6 +9,7 @@ var TableNames = struct { Exchange string Script string ScriptExecution string + Trade string WithdrawalCrypto string WithdrawalFiat string WithdrawalHistory string @@ -18,6 +19,7 @@ var TableNames = struct { Exchange: "exchange", Script: "script", ScriptExecution: "script_execution", + Trade: "trade", WithdrawalCrypto: "withdrawal_crypto", WithdrawalFiat: "withdrawal_fiat", WithdrawalHistory: "withdrawal_history", diff --git a/database/models/postgres/exchange.go b/database/models/postgres/exchange.go index 36a7dcbc..10ed22a9 100644 --- a/database/models/postgres/exchange.go +++ b/database/models/postgres/exchange.go @@ -51,15 +51,18 @@ var ExchangeWhere = struct { // ExchangeRels is where relationship names are stored. var ExchangeRels = struct { ExchangeNameCandles string + ExchangeNameTrades string ExchangeNameWithdrawalHistories string }{ ExchangeNameCandles: "ExchangeNameCandles", + ExchangeNameTrades: "ExchangeNameTrades", ExchangeNameWithdrawalHistories: "ExchangeNameWithdrawalHistories", } // exchangeR is where relationships are stored. type exchangeR struct { ExchangeNameCandles CandleSlice + ExchangeNameTrades TradeSlice ExchangeNameWithdrawalHistories WithdrawalHistorySlice } @@ -374,6 +377,27 @@ func (o *Exchange) ExchangeNameCandles(mods ...qm.QueryMod) candleQuery { return query } +// ExchangeNameTrades retrieves all the trade's Trades with an executor via exchange_name_id column. +func (o *Exchange) ExchangeNameTrades(mods ...qm.QueryMod) tradeQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"trade\".\"exchange_name_id\"=?", o.ID), + ) + + query := Trades(queryMods...) + queries.SetFrom(query.Query, "\"trade\"") + + if len(queries.GetSelect(query.Query)) == 0 { + queries.SetSelect(query.Query, []string{"\"trade\".*"}) + } + + return query +} + // ExchangeNameWithdrawalHistories retrieves all the withdrawal_history's WithdrawalHistories with an executor via exchange_name_id column. func (o *Exchange) ExchangeNameWithdrawalHistories(mods ...qm.QueryMod) withdrawalHistoryQuery { var queryMods []qm.QueryMod @@ -490,6 +514,101 @@ func (exchangeL) LoadExchangeNameCandles(ctx context.Context, e boil.ContextExec return nil } +// LoadExchangeNameTrades allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (exchangeL) LoadExchangeNameTrades(ctx context.Context, e boil.ContextExecutor, singular bool, maybeExchange interface{}, mods queries.Applicator) error { + var slice []*Exchange + var object *Exchange + + if singular { + object = maybeExchange.(*Exchange) + } else { + slice = *maybeExchange.(*[]*Exchange) + } + + args := make([]interface{}, 0, 1) + if singular { + if object.R == nil { + object.R = &exchangeR{} + } + args = append(args, object.ID) + } else { + Outer: + for _, obj := range slice { + if obj.R == nil { + obj.R = &exchangeR{} + } + + for _, a := range args { + if a == obj.ID { + continue Outer + } + } + + args = append(args, obj.ID) + } + } + + if len(args) == 0 { + return nil + } + + query := NewQuery(qm.From(`trade`), qm.WhereIn(`trade.exchange_name_id in ?`, args...)) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load trade") + } + + var resultSlice []*Trade + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice trade") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on trade") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for trade") + } + + if len(tradeAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.ExchangeNameTrades = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &tradeR{} + } + foreign.R.ExchangeName = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if local.ID == foreign.ExchangeNameID { + local.R.ExchangeNameTrades = append(local.R.ExchangeNameTrades, foreign) + if foreign.R == nil { + foreign.R = &tradeR{} + } + foreign.R.ExchangeName = local + break + } + } + } + + return nil +} + // LoadExchangeNameWithdrawalHistories allows an eager lookup of values, cached into the // loaded structs of the objects. This is for a 1-M or N-M relationship. func (exchangeL) LoadExchangeNameWithdrawalHistories(ctx context.Context, e boil.ContextExecutor, singular bool, maybeExchange interface{}, mods queries.Applicator) error { @@ -638,6 +757,59 @@ func (o *Exchange) AddExchangeNameCandles(ctx context.Context, exec boil.Context return nil } +// AddExchangeNameTrades adds the given related objects to the existing relationships +// of the exchange, optionally inserting them as new records. +// Appends related to o.R.ExchangeNameTrades. +// Sets related.R.ExchangeName appropriately. +func (o *Exchange) AddExchangeNameTrades(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Trade) error { + var err error + for _, rel := range related { + if insert { + rel.ExchangeNameID = o.ID + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"exchange_name_id"}), + strmangle.WhereClause("\"", "\"", 2, tradePrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) + } + + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + rel.ExchangeNameID = o.ID + } + } + + if o.R == nil { + o.R = &exchangeR{ + ExchangeNameTrades: related, + } + } else { + o.R.ExchangeNameTrades = append(o.R.ExchangeNameTrades, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &tradeR{ + ExchangeName: o, + } + } else { + rel.R.ExchangeName = o + } + } + return nil +} + // AddExchangeNameWithdrawalHistories adds the given related objects to the existing relationships // of the exchange, optionally inserting them as new records. // Appends related to o.R.ExchangeNameWithdrawalHistories. diff --git a/database/models/postgres/exchange_test.go b/database/models/postgres/exchange_test.go index def86bd2..b41e50c1 100644 --- a/database/models/postgres/exchange_test.go +++ b/database/models/postgres/exchange_test.go @@ -572,6 +572,84 @@ func testExchangeToManyExchangeNameCandles(t *testing.T) { } } +func testExchangeToManyExchangeNameTrades(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Exchange + var b, c Trade + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, exchangeDBTypes, true, exchangeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Exchange struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + b.ExchangeNameID = a.ID + c.ExchangeNameID = a.ID + + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.ExchangeNameTrades().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if v.ExchangeNameID == b.ExchangeNameID { + bFound = true + } + if v.ExchangeNameID == c.ExchangeNameID { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := ExchangeSlice{&a} + if err = a.L.LoadExchangeNameTrades(ctx, tx, false, (*[]*Exchange)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.ExchangeNameTrades); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.ExchangeNameTrades = nil + if err = a.L.LoadExchangeNameTrades(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.ExchangeNameTrades); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + func testExchangeToManyExchangeNameWithdrawalHistories(t *testing.T) { var err error ctx := context.Background() @@ -725,6 +803,81 @@ func testExchangeToManyAddOpExchangeNameCandles(t *testing.T) { } } } +func testExchangeToManyAddOpExchangeNameTrades(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Exchange + var b, c, d, e Trade + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Trade{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, tradeDBTypes, false, strmangle.SetComplement(tradePrimaryKeyColumns, tradeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Trade{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddExchangeNameTrades(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if a.ID != first.ExchangeNameID { + t.Error("foreign key was wrong value", a.ID, first.ExchangeNameID) + } + if a.ID != second.ExchangeNameID { + t.Error("foreign key was wrong value", a.ID, second.ExchangeNameID) + } + + if first.R.ExchangeName != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.ExchangeName != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.ExchangeNameTrades[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.ExchangeNameTrades[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.ExchangeNameTrades().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} func testExchangeToManyAddOpExchangeNameWithdrawalHistories(t *testing.T) { var err error diff --git a/database/models/postgres/trade.go b/database/models/postgres/trade.go new file mode 100644 index 00000000..1cea7b51 --- /dev/null +++ b/database/models/postgres/trade.go @@ -0,0 +1,1071 @@ +// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package postgres + +import ( + "context" + "database/sql" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/thrasher-corp/sqlboiler/boil" + "github.com/thrasher-corp/sqlboiler/queries" + "github.com/thrasher-corp/sqlboiler/queries/qm" + "github.com/thrasher-corp/sqlboiler/queries/qmhelper" + "github.com/thrasher-corp/sqlboiler/strmangle" + "github.com/volatiletech/null" +) + +// Trade is an object representing the database table. +type Trade struct { + ID string `boil:"id" json:"id" toml:"id" yaml:"id"` + ExchangeNameID string `boil:"exchange_name_id" json:"exchange_name_id" toml:"exchange_name_id" yaml:"exchange_name_id"` + Tid null.String `boil:"tid" json:"tid,omitempty" toml:"tid" yaml:"tid,omitempty"` + Base string `boil:"base" json:"base" toml:"base" yaml:"base"` + Quote string `boil:"quote" json:"quote" toml:"quote" yaml:"quote"` + Asset string `boil:"asset" json:"asset" toml:"asset" yaml:"asset"` + Price float64 `boil:"price" json:"price" toml:"price" yaml:"price"` + Amount float64 `boil:"amount" json:"amount" toml:"amount" yaml:"amount"` + Side null.String `boil:"side" json:"side,omitempty" toml:"side" yaml:"side,omitempty"` + Timestamp time.Time `boil:"timestamp" json:"timestamp" toml:"timestamp" yaml:"timestamp"` + + R *tradeR `boil:"-" json:"-" toml:"-" yaml:"-"` + L tradeL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var TradeColumns = struct { + ID string + ExchangeNameID string + Tid string + Base string + Quote string + Asset string + Price string + Amount string + Side string + Timestamp string +}{ + ID: "id", + ExchangeNameID: "exchange_name_id", + Tid: "tid", + Base: "base", + Quote: "quote", + Asset: "asset", + Price: "price", + Amount: "amount", + Side: "side", + Timestamp: "timestamp", +} + +// Generated where + +var TradeWhere = struct { + ID whereHelperstring + ExchangeNameID whereHelperstring + Tid whereHelpernull_String + Base whereHelperstring + Quote whereHelperstring + Asset whereHelperstring + Price whereHelperfloat64 + Amount whereHelperfloat64 + Side whereHelpernull_String + Timestamp whereHelpertime_Time +}{ + ID: whereHelperstring{field: "\"trade\".\"id\""}, + ExchangeNameID: whereHelperstring{field: "\"trade\".\"exchange_name_id\""}, + Tid: whereHelpernull_String{field: "\"trade\".\"tid\""}, + Base: whereHelperstring{field: "\"trade\".\"base\""}, + Quote: whereHelperstring{field: "\"trade\".\"quote\""}, + Asset: whereHelperstring{field: "\"trade\".\"asset\""}, + Price: whereHelperfloat64{field: "\"trade\".\"price\""}, + Amount: whereHelperfloat64{field: "\"trade\".\"amount\""}, + Side: whereHelpernull_String{field: "\"trade\".\"side\""}, + Timestamp: whereHelpertime_Time{field: "\"trade\".\"timestamp\""}, +} + +// TradeRels is where relationship names are stored. +var TradeRels = struct { + ExchangeName string +}{ + ExchangeName: "ExchangeName", +} + +// tradeR is where relationships are stored. +type tradeR struct { + ExchangeName *Exchange +} + +// NewStruct creates a new relationship struct +func (*tradeR) NewStruct() *tradeR { + return &tradeR{} +} + +// tradeL is where Load methods for each relationship are stored. +type tradeL struct{} + +var ( + tradeAllColumns = []string{"id", "exchange_name_id", "tid", "base", "quote", "asset", "price", "amount", "side", "timestamp"} + tradeColumnsWithoutDefault = []string{"exchange_name_id", "tid", "base", "quote", "asset", "price", "amount", "side", "timestamp"} + tradeColumnsWithDefault = []string{"id"} + tradePrimaryKeyColumns = []string{"id"} +) + +type ( + // TradeSlice is an alias for a slice of pointers to Trade. + // This should generally be used opposed to []Trade. + TradeSlice []*Trade + // TradeHook is the signature for custom Trade hook methods + TradeHook func(context.Context, boil.ContextExecutor, *Trade) error + + tradeQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + tradeType = reflect.TypeOf(&Trade{}) + tradeMapping = queries.MakeStructMapping(tradeType) + tradePrimaryKeyMapping, _ = queries.BindMapping(tradeType, tradeMapping, tradePrimaryKeyColumns) + tradeInsertCacheMut sync.RWMutex + tradeInsertCache = make(map[string]insertCache) + tradeUpdateCacheMut sync.RWMutex + tradeUpdateCache = make(map[string]updateCache) + tradeUpsertCacheMut sync.RWMutex + tradeUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +var tradeBeforeInsertHooks []TradeHook +var tradeBeforeUpdateHooks []TradeHook +var tradeBeforeDeleteHooks []TradeHook +var tradeBeforeUpsertHooks []TradeHook + +var tradeAfterInsertHooks []TradeHook +var tradeAfterSelectHooks []TradeHook +var tradeAfterUpdateHooks []TradeHook +var tradeAfterDeleteHooks []TradeHook +var tradeAfterUpsertHooks []TradeHook + +// doBeforeInsertHooks executes all "before insert" hooks. +func (o *Trade) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpdateHooks executes all "before Update" hooks. +func (o *Trade) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeDeleteHooks executes all "before Delete" hooks. +func (o *Trade) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpsertHooks executes all "before Upsert" hooks. +func (o *Trade) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterInsertHooks executes all "after Insert" hooks. +func (o *Trade) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterSelectHooks executes all "after Select" hooks. +func (o *Trade) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterSelectHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpdateHooks executes all "after Update" hooks. +func (o *Trade) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterDeleteHooks executes all "after Delete" hooks. +func (o *Trade) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpsertHooks executes all "after Upsert" hooks. +func (o *Trade) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// AddTradeHook registers your hook function for all future operations. +func AddTradeHook(hookPoint boil.HookPoint, tradeHook TradeHook) { + switch hookPoint { + case boil.BeforeInsertHook: + tradeBeforeInsertHooks = append(tradeBeforeInsertHooks, tradeHook) + case boil.BeforeUpdateHook: + tradeBeforeUpdateHooks = append(tradeBeforeUpdateHooks, tradeHook) + case boil.BeforeDeleteHook: + tradeBeforeDeleteHooks = append(tradeBeforeDeleteHooks, tradeHook) + case boil.BeforeUpsertHook: + tradeBeforeUpsertHooks = append(tradeBeforeUpsertHooks, tradeHook) + case boil.AfterInsertHook: + tradeAfterInsertHooks = append(tradeAfterInsertHooks, tradeHook) + case boil.AfterSelectHook: + tradeAfterSelectHooks = append(tradeAfterSelectHooks, tradeHook) + case boil.AfterUpdateHook: + tradeAfterUpdateHooks = append(tradeAfterUpdateHooks, tradeHook) + case boil.AfterDeleteHook: + tradeAfterDeleteHooks = append(tradeAfterDeleteHooks, tradeHook) + case boil.AfterUpsertHook: + tradeAfterUpsertHooks = append(tradeAfterUpsertHooks, tradeHook) + } +} + +// One returns a single trade record from the query. +func (q tradeQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Trade, error) { + o := &Trade{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(ctx, exec, o) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "postgres: failed to execute a one query for trade") + } + + if err := o.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + + return o, nil +} + +// All returns all Trade records from the query. +func (q tradeQuery) All(ctx context.Context, exec boil.ContextExecutor) (TradeSlice, error) { + var o []*Trade + + err := q.Bind(ctx, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "postgres: failed to assign all query results to Trade slice") + } + + if len(tradeAfterSelectHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + } + } + + return o, nil +} + +// Count returns the count of all Trade records in the query. +func (q tradeQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "postgres: failed to count trade rows") + } + + return count, nil +} + +// Exists checks if the row exists in the table. +func (q tradeQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "postgres: failed to check if trade exists") + } + + return count > 0, nil +} + +// ExchangeName pointed to by the foreign key. +func (o *Trade) ExchangeName(mods ...qm.QueryMod) exchangeQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.ExchangeNameID), + } + + queryMods = append(queryMods, mods...) + + query := Exchanges(queryMods...) + queries.SetFrom(query.Query, "\"exchange\"") + + return query +} + +// LoadExchangeName allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (tradeL) LoadExchangeName(ctx context.Context, e boil.ContextExecutor, singular bool, maybeTrade interface{}, mods queries.Applicator) error { + var slice []*Trade + var object *Trade + + if singular { + object = maybeTrade.(*Trade) + } else { + slice = *maybeTrade.(*[]*Trade) + } + + args := make([]interface{}, 0, 1) + if singular { + if object.R == nil { + object.R = &tradeR{} + } + args = append(args, object.ExchangeNameID) + + } else { + Outer: + for _, obj := range slice { + if obj.R == nil { + obj.R = &tradeR{} + } + + for _, a := range args { + if a == obj.ExchangeNameID { + continue Outer + } + } + + args = append(args, obj.ExchangeNameID) + + } + } + + if len(args) == 0 { + return nil + } + + query := NewQuery(qm.From(`exchange`), qm.WhereIn(`exchange.id in ?`, args...)) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Exchange") + } + + var resultSlice []*Exchange + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Exchange") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for exchange") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for exchange") + } + + if len(tradeAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.ExchangeName = foreign + if foreign.R == nil { + foreign.R = &exchangeR{} + } + foreign.R.ExchangeNameTrades = append(foreign.R.ExchangeNameTrades, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if local.ExchangeNameID == foreign.ID { + local.R.ExchangeName = foreign + if foreign.R == nil { + foreign.R = &exchangeR{} + } + foreign.R.ExchangeNameTrades = append(foreign.R.ExchangeNameTrades, local) + break + } + } + } + + return nil +} + +// SetExchangeName of the trade to the related item. +// Sets o.R.ExchangeName to related. +// Adds o to related.R.ExchangeNameTrades. +func (o *Trade) SetExchangeName(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Exchange) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"exchange_name_id"}), + strmangle.WhereClause("\"", "\"", 2, tradePrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) + } + + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + o.ExchangeNameID = related.ID + if o.R == nil { + o.R = &tradeR{ + ExchangeName: related, + } + } else { + o.R.ExchangeName = related + } + + if related.R == nil { + related.R = &exchangeR{ + ExchangeNameTrades: TradeSlice{o}, + } + } else { + related.R.ExchangeNameTrades = append(related.R.ExchangeNameTrades, o) + } + + return nil +} + +// Trades retrieves all the records using an executor. +func Trades(mods ...qm.QueryMod) tradeQuery { + mods = append(mods, qm.From("\"trade\"")) + return tradeQuery{NewQuery(mods...)} +} + +// FindTrade retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindTrade(ctx context.Context, exec boil.ContextExecutor, iD string, selectCols ...string) (*Trade, error) { + tradeObj := &Trade{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from \"trade\" where \"id\"=$1", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(ctx, exec, tradeObj) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "postgres: unable to select from trade") + } + + return tradeObj, nil +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Trade) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { + if o == nil { + return errors.New("postgres: no trade provided for insertion") + } + + var err error + + if err := o.doBeforeInsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(tradeColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + tradeInsertCacheMut.RLock() + cache, cached := tradeInsertCache[key] + tradeInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + tradeAllColumns, + tradeColumnsWithDefault, + tradeColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(tradeType, tradeMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(tradeType, tradeMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO \"trade\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO \"trade\" %sDEFAULT VALUES%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + queryReturning = fmt.Sprintf(" RETURNING \"%s\"", strings.Join(returnColumns, "\",\"")) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) + } + + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + + if err != nil { + return errors.Wrap(err, "postgres: unable to insert into trade") + } + + if !cached { + tradeInsertCacheMut.Lock() + tradeInsertCache[key] = cache + tradeInsertCacheMut.Unlock() + } + + return o.doAfterInsertHooks(ctx, exec) +} + +// Update uses an executor to update the Trade. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Trade) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) { + var err error + if err = o.doBeforeUpdateHooks(ctx, exec); err != nil { + return 0, err + } + key := makeCacheKey(columns, nil) + tradeUpdateCacheMut.RLock() + cache, cached := tradeUpdateCache[key] + tradeUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + tradeAllColumns, + tradePrimaryKeyColumns, + ) + + if len(wl) == 0 { + return 0, errors.New("postgres: unable to update trade, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, wl), + strmangle.WhereClause("\"", "\"", len(wl)+1, tradePrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(tradeType, tradeMapping, append(wl, tradePrimaryKeyColumns...)) + if err != nil { + return 0, err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, values) + } + + var result sql.Result + result, err = exec.ExecContext(ctx, cache.query, values...) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to update trade row") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: failed to get rows affected by update for trade") + } + + if !cached { + tradeUpdateCacheMut.Lock() + tradeUpdateCache[key] = cache + tradeUpdateCacheMut.Unlock() + } + + return rowsAff, o.doAfterUpdateHooks(ctx, exec) +} + +// UpdateAll updates all rows with the specified column values. +func (q tradeQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + queries.SetUpdate(q.Query, cols) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to update all for trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to retrieve rows affected for trade") + } + + return rowsAff, nil +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o TradeSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + ln := int64(len(o)) + if ln == 0 { + return 0, nil + } + + if len(cols) == 0 { + return 0, errors.New("postgres: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), len(colNames)+1, tradePrimaryKeyColumns, len(o))) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to update all in trade slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to retrieve rows affected all in update all trade") + } + return rowsAff, nil +} + +// Upsert attempts an insert using an executor, and does an update or ignore on conflict. +// See boil.Columns documentation for how to properly use updateColumns and insertColumns. +func (o *Trade) Upsert(ctx context.Context, exec boil.ContextExecutor, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns) error { + if o == nil { + return errors.New("postgres: no trade provided for upsert") + } + + if err := o.doBeforeUpsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(tradeColumnsWithDefault, o) + + // Build cache key in-line uglily - mysql vs psql problems + buf := strmangle.GetBuffer() + if updateOnConflict { + buf.WriteByte('t') + } else { + buf.WriteByte('f') + } + buf.WriteByte('.') + for _, c := range conflictColumns { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(updateColumns.Kind)) + for _, c := range updateColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(insertColumns.Kind)) + for _, c := range insertColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzDefaults { + buf.WriteString(c) + } + key := buf.String() + strmangle.PutBuffer(buf) + + tradeUpsertCacheMut.RLock() + cache, cached := tradeUpsertCache[key] + tradeUpsertCacheMut.RUnlock() + + var err error + + if !cached { + insert, ret := insertColumns.InsertColumnSet( + tradeAllColumns, + tradeColumnsWithDefault, + tradeColumnsWithoutDefault, + nzDefaults, + ) + update := updateColumns.UpdateColumnSet( + tradeAllColumns, + tradePrimaryKeyColumns, + ) + + if updateOnConflict && len(update) == 0 { + return errors.New("postgres: unable to upsert trade, could not build update column list") + } + + conflict := conflictColumns + if len(conflict) == 0 { + conflict = make([]string, len(tradePrimaryKeyColumns)) + copy(conflict, tradePrimaryKeyColumns) + } + cache.query = buildUpsertQueryPostgres(dialect, "\"trade\"", updateOnConflict, ret, update, conflict, insert) + + cache.valueMapping, err = queries.BindMapping(tradeType, tradeMapping, insert) + if err != nil { + return err + } + if len(ret) != 0 { + cache.retMapping, err = queries.BindMapping(tradeType, tradeMapping, ret) + if err != nil { + return err + } + } + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + var returns []interface{} + if len(cache.retMapping) != 0 { + returns = queries.PtrsFromMapping(value, cache.retMapping) + } + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) + } + + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...) + if err == sql.ErrNoRows { + err = nil // Postgres doesn't return anything when there's no update + } + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + if err != nil { + return errors.Wrap(err, "postgres: unable to upsert trade") + } + + if !cached { + tradeUpsertCacheMut.Lock() + tradeUpsertCache[key] = cache + tradeUpsertCacheMut.Unlock() + } + + return o.doAfterUpsertHooks(ctx, exec) +} + +// Delete deletes a single Trade record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Trade) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if o == nil { + return 0, errors.New("postgres: no Trade provided for delete") + } + + if err := o.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), tradePrimaryKeyMapping) + sql := "DELETE FROM \"trade\" WHERE \"id\"=$1" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to delete from trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: failed to get rows affected by delete for trade") + } + + if err := o.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + return rowsAff, nil +} + +// DeleteAll deletes all matching rows. +func (q tradeQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if q.Query == nil { + return 0, errors.New("postgres: no tradeQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to delete all from trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: failed to get rows affected by deleteall for trade") + } + + return rowsAff, nil +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o TradeSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if len(o) == 0 { + return 0, nil + } + + if len(tradeBeforeDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM \"trade\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, tradePrimaryKeyColumns, len(o)) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "postgres: unable to delete all from trade slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "postgres: failed to get rows affected by deleteall for trade") + } + + if len(tradeAfterDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + return rowsAff, nil +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Trade) Reload(ctx context.Context, exec boil.ContextExecutor) error { + ret, err := FindTrade(ctx, exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *TradeSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := TradeSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT \"trade\".* FROM \"trade\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, tradePrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(ctx, exec, &slice) + if err != nil { + return errors.Wrap(err, "postgres: unable to reload all in TradeSlice") + } + + *o = slice + + return nil +} + +// TradeExists checks if the Trade row exists. +func TradeExists(ctx context.Context, exec boil.ContextExecutor, iD string) (bool, error) { + var exists bool + sql := "select exists(select 1 from \"trade\" where \"id\"=$1 limit 1)" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, iD) + } + + row := exec.QueryRowContext(ctx, sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "postgres: unable to check if trade exists") + } + + return exists, nil +} diff --git a/database/models/postgres/trade_test.go b/database/models/postgres/trade_test.go new file mode 100644 index 00000000..c0441436 --- /dev/null +++ b/database/models/postgres/trade_test.go @@ -0,0 +1,841 @@ +// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package postgres + +import ( + "bytes" + "context" + "reflect" + "testing" + + "github.com/thrasher-corp/sqlboiler/boil" + "github.com/thrasher-corp/sqlboiler/queries" + "github.com/thrasher-corp/sqlboiler/randomize" + "github.com/thrasher-corp/sqlboiler/strmangle" +) + +var ( + // Relationships sometimes use the reflection helper queries.Equal/queries.Assign + // so force a package dependency in case they don't. + _ = queries.Equal +) + +func testTrades(t *testing.T) { + t.Parallel() + + query := Trades() + + if query.Query == nil { + t.Error("expected a query, got nothing") + } +} + +func testTradesDelete(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := o.Delete(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesQueryDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := Trades().DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesSliceDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := TradeSlice{o} + + if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesExists(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + e, err := TradeExists(ctx, tx, o.ID) + if err != nil { + t.Errorf("Unable to check if Trade exists: %s", err) + } + if !e { + t.Errorf("Expected TradeExists to return true, but got false.") + } +} + +func testTradesFind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + tradeFound, err := FindTrade(ctx, tx, o.ID) + if err != nil { + t.Error(err) + } + + if tradeFound == nil { + t.Error("want a record, got nil") + } +} + +func testTradesBind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = Trades().Bind(ctx, tx, o); err != nil { + t.Error(err) + } +} + +func testTradesOne(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if x, err := Trades().One(ctx, tx); err != nil { + t.Error(err) + } else if x == nil { + t.Error("expected to get a non nil record") + } +} + +func testTradesAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + tradeOne := &Trade{} + tradeTwo := &Trade{} + if err = randomize.Struct(seed, tradeOne, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err = randomize.Struct(seed, tradeTwo, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = tradeOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = tradeTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Trades().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 2 { + t.Error("want 2 records, got:", len(slice)) + } +} + +func testTradesCount(t *testing.T) { + t.Parallel() + + var err error + seed := randomize.NewSeed() + tradeOne := &Trade{} + tradeTwo := &Trade{} + if err = randomize.Struct(seed, tradeOne, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err = randomize.Struct(seed, tradeTwo, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = tradeOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = tradeTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 2 { + t.Error("want 2 records, got:", count) + } +} + +func tradeBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func testTradesHooks(t *testing.T) { + t.Parallel() + + var err error + + ctx := context.Background() + empty := &Trade{} + o := &Trade{} + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, o, tradeDBTypes, false); err != nil { + t.Errorf("Unable to randomize Trade object: %s", err) + } + + AddTradeHook(boil.BeforeInsertHook, tradeBeforeInsertHook) + if err = o.doBeforeInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o) + } + tradeBeforeInsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterInsertHook, tradeAfterInsertHook) + if err = o.doAfterInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o) + } + tradeAfterInsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterSelectHook, tradeAfterSelectHook) + if err = o.doAfterSelectHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterSelectHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o) + } + tradeAfterSelectHooks = []TradeHook{} + + AddTradeHook(boil.BeforeUpdateHook, tradeBeforeUpdateHook) + if err = o.doBeforeUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o) + } + tradeBeforeUpdateHooks = []TradeHook{} + + AddTradeHook(boil.AfterUpdateHook, tradeAfterUpdateHook) + if err = o.doAfterUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o) + } + tradeAfterUpdateHooks = []TradeHook{} + + AddTradeHook(boil.BeforeDeleteHook, tradeBeforeDeleteHook) + if err = o.doBeforeDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o) + } + tradeBeforeDeleteHooks = []TradeHook{} + + AddTradeHook(boil.AfterDeleteHook, tradeAfterDeleteHook) + if err = o.doAfterDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o) + } + tradeAfterDeleteHooks = []TradeHook{} + + AddTradeHook(boil.BeforeUpsertHook, tradeBeforeUpsertHook) + if err = o.doBeforeUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o) + } + tradeBeforeUpsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterUpsertHook, tradeAfterUpsertHook) + if err = o.doAfterUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o) + } + tradeAfterUpsertHooks = []TradeHook{} +} + +func testTradesInsert(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testTradesInsertWhitelist(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Whitelist(tradeColumnsWithoutDefault...)); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testTradeToOneExchangeUsingExchangeName(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Trade + var foreign Exchange + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, exchangeDBTypes, false, exchangeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Exchange struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + local.ExchangeNameID = foreign.ID + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.ExchangeName().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if check.ID != foreign.ID { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + slice := TradeSlice{&local} + if err = local.L.LoadExchangeName(ctx, tx, false, (*[]*Trade)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeName == nil { + t.Error("struct should have been eager loaded") + } + + local.R.ExchangeName = nil + if err = local.L.LoadExchangeName(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeName == nil { + t.Error("struct should have been eager loaded") + } +} + +func testTradeToOneSetOpExchangeUsingExchangeName(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Trade + var b, c Exchange + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, tradeDBTypes, false, strmangle.SetComplement(tradePrimaryKeyColumns, tradeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Exchange{&b, &c} { + err = a.SetExchangeName(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.ExchangeName != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.ExchangeNameTrades[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if a.ExchangeNameID != x.ID { + t.Error("foreign key was wrong value", a.ExchangeNameID) + } + + zero := reflect.Zero(reflect.TypeOf(a.ExchangeNameID)) + reflect.Indirect(reflect.ValueOf(&a.ExchangeNameID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if a.ExchangeNameID != x.ID { + t.Error("foreign key was wrong value", a.ExchangeNameID, x.ID) + } + } +} + +func testTradesReload(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = o.Reload(ctx, tx); err != nil { + t.Error(err) + } +} + +func testTradesReloadAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := TradeSlice{o} + + if err = slice.ReloadAll(ctx, tx); err != nil { + t.Error(err) + } +} + +func testTradesSelect(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Trades().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 1 { + t.Error("want one record, got:", len(slice)) + } +} + +var ( + tradeDBTypes = map[string]string{`ID`: `uuid`, `ExchangeNameID`: `uuid`, `Tid`: `character varying`, `Base`: `character varying`, `Quote`: `character varying`, `Asset`: `character varying`, `Price`: `double precision`, `Amount`: `double precision`, `Side`: `character varying`, `Timestamp`: `timestamp with time zone`} + _ = bytes.MinRead +) + +func testTradesUpdate(t *testing.T) { + t.Parallel() + + if 0 == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with no primary key columns") + } + if len(tradeAllColumns) == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only affect one row but affected", rowsAff) + } +} + +func testTradesSliceUpdateAll(t *testing.T) { + t.Parallel() + + if len(tradeAllColumns) == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + // Remove Primary keys and unique columns from what we plan to update + var fields []string + if strmangle.StringSliceMatch(tradeAllColumns, tradePrimaryKeyColumns) { + fields = tradeAllColumns + } else { + fields = strmangle.SetComplement( + tradeAllColumns, + tradePrimaryKeyColumns, + ) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + typ := reflect.TypeOf(o).Elem() + n := typ.NumField() + + updateMap := M{} + for _, col := range fields { + for i := 0; i < n; i++ { + f := typ.Field(i) + if f.Tag.Get("boil") == col { + updateMap[col] = value.Field(i).Interface() + } + } + } + + slice := TradeSlice{o} + if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("wanted one record updated but got", rowsAff) + } +} + +func testTradesUpsert(t *testing.T) { + t.Parallel() + + if len(tradeAllColumns) == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + // Attempt the INSERT side of an UPSERT + o := Trade{} + if err = randomize.Struct(seed, &o, tradeDBTypes, true); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Upsert(ctx, tx, false, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Trade: %s", err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } + + // Attempt the UPDATE side of an UPSERT + if err = randomize.Struct(seed, &o, tradeDBTypes, false, tradePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + if err = o.Upsert(ctx, tx, true, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Trade: %s", err) + } + + count, err = Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } +} diff --git a/database/models/sqlite3/boil_suites_test.go b/database/models/sqlite3/boil_suites_test.go index 821f981d..741a643b 100644 --- a/database/models/sqlite3/boil_suites_test.go +++ b/database/models/sqlite3/boil_suites_test.go @@ -17,6 +17,7 @@ func TestParent(t *testing.T) { t.Run("Exchanges", testExchanges) t.Run("Scripts", testScripts) t.Run("ScriptExecutions", testScriptExecutions) + t.Run("Trades", testTrades) t.Run("WithdrawalCryptos", testWithdrawalCryptos) t.Run("WithdrawalFiats", testWithdrawalFiats) t.Run("WithdrawalHistories", testWithdrawalHistories) @@ -28,6 +29,7 @@ func TestDelete(t *testing.T) { t.Run("Exchanges", testExchangesDelete) t.Run("Scripts", testScriptsDelete) t.Run("ScriptExecutions", testScriptExecutionsDelete) + t.Run("Trades", testTradesDelete) t.Run("WithdrawalCryptos", testWithdrawalCryptosDelete) t.Run("WithdrawalFiats", testWithdrawalFiatsDelete) t.Run("WithdrawalHistories", testWithdrawalHistoriesDelete) @@ -39,6 +41,7 @@ func TestQueryDeleteAll(t *testing.T) { t.Run("Exchanges", testExchangesQueryDeleteAll) t.Run("Scripts", testScriptsQueryDeleteAll) t.Run("ScriptExecutions", testScriptExecutionsQueryDeleteAll) + t.Run("Trades", testTradesQueryDeleteAll) t.Run("WithdrawalCryptos", testWithdrawalCryptosQueryDeleteAll) t.Run("WithdrawalFiats", testWithdrawalFiatsQueryDeleteAll) t.Run("WithdrawalHistories", testWithdrawalHistoriesQueryDeleteAll) @@ -50,6 +53,7 @@ func TestSliceDeleteAll(t *testing.T) { t.Run("Exchanges", testExchangesSliceDeleteAll) t.Run("Scripts", testScriptsSliceDeleteAll) t.Run("ScriptExecutions", testScriptExecutionsSliceDeleteAll) + t.Run("Trades", testTradesSliceDeleteAll) t.Run("WithdrawalCryptos", testWithdrawalCryptosSliceDeleteAll) t.Run("WithdrawalFiats", testWithdrawalFiatsSliceDeleteAll) t.Run("WithdrawalHistories", testWithdrawalHistoriesSliceDeleteAll) @@ -61,6 +65,7 @@ func TestExists(t *testing.T) { t.Run("Exchanges", testExchangesExists) t.Run("Scripts", testScriptsExists) t.Run("ScriptExecutions", testScriptExecutionsExists) + t.Run("Trades", testTradesExists) t.Run("WithdrawalCryptos", testWithdrawalCryptosExists) t.Run("WithdrawalFiats", testWithdrawalFiatsExists) t.Run("WithdrawalHistories", testWithdrawalHistoriesExists) @@ -72,6 +77,7 @@ func TestFind(t *testing.T) { t.Run("Exchanges", testExchangesFind) t.Run("Scripts", testScriptsFind) t.Run("ScriptExecutions", testScriptExecutionsFind) + t.Run("Trades", testTradesFind) t.Run("WithdrawalCryptos", testWithdrawalCryptosFind) t.Run("WithdrawalFiats", testWithdrawalFiatsFind) t.Run("WithdrawalHistories", testWithdrawalHistoriesFind) @@ -83,6 +89,7 @@ func TestBind(t *testing.T) { t.Run("Exchanges", testExchangesBind) t.Run("Scripts", testScriptsBind) t.Run("ScriptExecutions", testScriptExecutionsBind) + t.Run("Trades", testTradesBind) t.Run("WithdrawalCryptos", testWithdrawalCryptosBind) t.Run("WithdrawalFiats", testWithdrawalFiatsBind) t.Run("WithdrawalHistories", testWithdrawalHistoriesBind) @@ -94,6 +101,7 @@ func TestOne(t *testing.T) { t.Run("Exchanges", testExchangesOne) t.Run("Scripts", testScriptsOne) t.Run("ScriptExecutions", testScriptExecutionsOne) + t.Run("Trades", testTradesOne) t.Run("WithdrawalCryptos", testWithdrawalCryptosOne) t.Run("WithdrawalFiats", testWithdrawalFiatsOne) t.Run("WithdrawalHistories", testWithdrawalHistoriesOne) @@ -105,6 +113,7 @@ func TestAll(t *testing.T) { t.Run("Exchanges", testExchangesAll) t.Run("Scripts", testScriptsAll) t.Run("ScriptExecutions", testScriptExecutionsAll) + t.Run("Trades", testTradesAll) t.Run("WithdrawalCryptos", testWithdrawalCryptosAll) t.Run("WithdrawalFiats", testWithdrawalFiatsAll) t.Run("WithdrawalHistories", testWithdrawalHistoriesAll) @@ -116,6 +125,7 @@ func TestCount(t *testing.T) { t.Run("Exchanges", testExchangesCount) t.Run("Scripts", testScriptsCount) t.Run("ScriptExecutions", testScriptExecutionsCount) + t.Run("Trades", testTradesCount) t.Run("WithdrawalCryptos", testWithdrawalCryptosCount) t.Run("WithdrawalFiats", testWithdrawalFiatsCount) t.Run("WithdrawalHistories", testWithdrawalHistoriesCount) @@ -127,6 +137,7 @@ func TestHooks(t *testing.T) { t.Run("Exchanges", testExchangesHooks) t.Run("Scripts", testScriptsHooks) t.Run("ScriptExecutions", testScriptExecutionsHooks) + t.Run("Trades", testTradesHooks) t.Run("WithdrawalCryptos", testWithdrawalCryptosHooks) t.Run("WithdrawalFiats", testWithdrawalFiatsHooks) t.Run("WithdrawalHistories", testWithdrawalHistoriesHooks) @@ -143,6 +154,8 @@ func TestInsert(t *testing.T) { t.Run("Scripts", testScriptsInsertWhitelist) t.Run("ScriptExecutions", testScriptExecutionsInsert) t.Run("ScriptExecutions", testScriptExecutionsInsertWhitelist) + t.Run("Trades", testTradesInsert) + t.Run("Trades", testTradesInsertWhitelist) t.Run("WithdrawalCryptos", testWithdrawalCryptosInsert) t.Run("WithdrawalCryptos", testWithdrawalCryptosInsertWhitelist) t.Run("WithdrawalFiats", testWithdrawalFiatsInsert) @@ -156,6 +169,7 @@ func TestInsert(t *testing.T) { func TestToOne(t *testing.T) { t.Run("CandleToExchangeUsingExchangeName", testCandleToOneExchangeUsingExchangeName) t.Run("ScriptExecutionToScriptUsingScript", testScriptExecutionToOneScriptUsingScript) + t.Run("TradeToExchangeUsingExchangeName", testTradeToOneExchangeUsingExchangeName) t.Run("WithdrawalCryptoToWithdrawalHistoryUsingWithdrawalHistory", testWithdrawalCryptoToOneWithdrawalHistoryUsingWithdrawalHistory) t.Run("WithdrawalFiatToWithdrawalHistoryUsingWithdrawalHistory", testWithdrawalFiatToOneWithdrawalHistoryUsingWithdrawalHistory) t.Run("WithdrawalHistoryToExchangeUsingExchangeName", testWithdrawalHistoryToOneExchangeUsingExchangeName) @@ -165,6 +179,7 @@ func TestToOne(t *testing.T) { // or deadlocks can occur. func TestOneToOne(t *testing.T) { t.Run("ExchangeToCandleUsingExchangeNameCandle", testExchangeOneToOneCandleUsingExchangeNameCandle) + t.Run("ExchangeToTradeUsingExchangeNameTrade", testExchangeOneToOneTradeUsingExchangeNameTrade) } // TestToMany tests cannot be run in parallel @@ -181,6 +196,7 @@ func TestToMany(t *testing.T) { func TestToOneSet(t *testing.T) { t.Run("CandleToExchangeUsingExchangeNameCandle", testCandleToOneSetOpExchangeUsingExchangeName) t.Run("ScriptExecutionToScriptUsingScriptExecutions", testScriptExecutionToOneSetOpScriptUsingScript) + t.Run("TradeToExchangeUsingExchangeNameTrade", testTradeToOneSetOpExchangeUsingExchangeName) t.Run("WithdrawalCryptoToWithdrawalHistoryUsingWithdrawalCryptos", testWithdrawalCryptoToOneSetOpWithdrawalHistoryUsingWithdrawalHistory) t.Run("WithdrawalFiatToWithdrawalHistoryUsingWithdrawalFiats", testWithdrawalFiatToOneSetOpWithdrawalHistoryUsingWithdrawalHistory) t.Run("WithdrawalHistoryToExchangeUsingExchangeNameWithdrawalHistories", testWithdrawalHistoryToOneSetOpExchangeUsingExchangeName) @@ -194,6 +210,7 @@ func TestToOneRemove(t *testing.T) {} // or deadlocks can occur. func TestOneToOneSet(t *testing.T) { t.Run("ExchangeToCandleUsingExchangeNameCandle", testExchangeOneToOneSetOpCandleUsingExchangeNameCandle) + t.Run("ExchangeToTradeUsingExchangeNameTrade", testExchangeOneToOneSetOpTradeUsingExchangeNameTrade) } // TestOneToOneRemove tests cannot be run in parallel @@ -223,6 +240,7 @@ func TestReload(t *testing.T) { t.Run("Exchanges", testExchangesReload) t.Run("Scripts", testScriptsReload) t.Run("ScriptExecutions", testScriptExecutionsReload) + t.Run("Trades", testTradesReload) t.Run("WithdrawalCryptos", testWithdrawalCryptosReload) t.Run("WithdrawalFiats", testWithdrawalFiatsReload) t.Run("WithdrawalHistories", testWithdrawalHistoriesReload) @@ -234,6 +252,7 @@ func TestReloadAll(t *testing.T) { t.Run("Exchanges", testExchangesReloadAll) t.Run("Scripts", testScriptsReloadAll) t.Run("ScriptExecutions", testScriptExecutionsReloadAll) + t.Run("Trades", testTradesReloadAll) t.Run("WithdrawalCryptos", testWithdrawalCryptosReloadAll) t.Run("WithdrawalFiats", testWithdrawalFiatsReloadAll) t.Run("WithdrawalHistories", testWithdrawalHistoriesReloadAll) @@ -245,6 +264,7 @@ func TestSelect(t *testing.T) { t.Run("Exchanges", testExchangesSelect) t.Run("Scripts", testScriptsSelect) t.Run("ScriptExecutions", testScriptExecutionsSelect) + t.Run("Trades", testTradesSelect) t.Run("WithdrawalCryptos", testWithdrawalCryptosSelect) t.Run("WithdrawalFiats", testWithdrawalFiatsSelect) t.Run("WithdrawalHistories", testWithdrawalHistoriesSelect) @@ -256,6 +276,7 @@ func TestUpdate(t *testing.T) { t.Run("Exchanges", testExchangesUpdate) t.Run("Scripts", testScriptsUpdate) t.Run("ScriptExecutions", testScriptExecutionsUpdate) + t.Run("Trades", testTradesUpdate) t.Run("WithdrawalCryptos", testWithdrawalCryptosUpdate) t.Run("WithdrawalFiats", testWithdrawalFiatsUpdate) t.Run("WithdrawalHistories", testWithdrawalHistoriesUpdate) @@ -267,6 +288,7 @@ func TestSliceUpdateAll(t *testing.T) { t.Run("Exchanges", testExchangesSliceUpdateAll) t.Run("Scripts", testScriptsSliceUpdateAll) t.Run("ScriptExecutions", testScriptExecutionsSliceUpdateAll) + t.Run("Trades", testTradesSliceUpdateAll) t.Run("WithdrawalCryptos", testWithdrawalCryptosSliceUpdateAll) t.Run("WithdrawalFiats", testWithdrawalFiatsSliceUpdateAll) t.Run("WithdrawalHistories", testWithdrawalHistoriesSliceUpdateAll) diff --git a/database/models/sqlite3/boil_table_names.go b/database/models/sqlite3/boil_table_names.go index 97944900..bdf0480b 100644 --- a/database/models/sqlite3/boil_table_names.go +++ b/database/models/sqlite3/boil_table_names.go @@ -7,8 +7,10 @@ var TableNames = struct { AuditEvent string Candle string Exchange string + GooseDBVersion string Script string ScriptExecution string + Trade string WithdrawalCrypto string WithdrawalFiat string WithdrawalHistory string @@ -16,8 +18,10 @@ var TableNames = struct { AuditEvent: "audit_event", Candle: "candle", Exchange: "exchange", + GooseDBVersion: "goose_db_version", Script: "script", ScriptExecution: "script_execution", + Trade: "trade", WithdrawalCrypto: "withdrawal_crypto", WithdrawalFiat: "withdrawal_fiat", WithdrawalHistory: "withdrawal_history", diff --git a/database/models/sqlite3/exchange.go b/database/models/sqlite3/exchange.go index 21d93091..11bc18bc 100644 --- a/database/models/sqlite3/exchange.go +++ b/database/models/sqlite3/exchange.go @@ -50,15 +50,18 @@ var ExchangeWhere = struct { // ExchangeRels is where relationship names are stored. var ExchangeRels = struct { ExchangeNameCandle string + ExchangeNameTrade string ExchangeNameWithdrawalHistories string }{ ExchangeNameCandle: "ExchangeNameCandle", + ExchangeNameTrade: "ExchangeNameTrade", ExchangeNameWithdrawalHistories: "ExchangeNameWithdrawalHistories", } // exchangeR is where relationships are stored. type exchangeR struct { ExchangeNameCandle *Candle + ExchangeNameTrade *Trade ExchangeNameWithdrawalHistories WithdrawalHistorySlice } @@ -366,6 +369,20 @@ func (o *Exchange) ExchangeNameCandle(mods ...qm.QueryMod) candleQuery { return query } +// ExchangeNameTrade pointed to by the foreign key. +func (o *Exchange) ExchangeNameTrade(mods ...qm.QueryMod) tradeQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"exchange_name_id\" = ?", o.ID), + } + + queryMods = append(queryMods, mods...) + + query := Trades(queryMods...) + queries.SetFrom(query.Query, "\"trade\"") + + return query +} + // ExchangeNameWithdrawalHistories retrieves all the withdrawal_history's WithdrawalHistories with an executor via exchange_name_id column. func (o *Exchange) ExchangeNameWithdrawalHistories(mods ...qm.QueryMod) withdrawalHistoryQuery { var queryMods []qm.QueryMod @@ -485,6 +502,104 @@ func (exchangeL) LoadExchangeNameCandle(ctx context.Context, e boil.ContextExecu return nil } +// LoadExchangeNameTrade allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-1 relationship. +func (exchangeL) LoadExchangeNameTrade(ctx context.Context, e boil.ContextExecutor, singular bool, maybeExchange interface{}, mods queries.Applicator) error { + var slice []*Exchange + var object *Exchange + + if singular { + object = maybeExchange.(*Exchange) + } else { + slice = *maybeExchange.(*[]*Exchange) + } + + args := make([]interface{}, 0, 1) + if singular { + if object.R == nil { + object.R = &exchangeR{} + } + args = append(args, object.ID) + } else { + Outer: + for _, obj := range slice { + if obj.R == nil { + obj.R = &exchangeR{} + } + + for _, a := range args { + if a == obj.ID { + continue Outer + } + } + + args = append(args, obj.ID) + } + } + + if len(args) == 0 { + return nil + } + + query := NewQuery(qm.From(`trade`), qm.WhereIn(`trade.exchange_name_id in ?`, args...)) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Trade") + } + + var resultSlice []*Trade + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Trade") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for trade") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for trade") + } + + if len(exchangeAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.ExchangeNameTrade = foreign + if foreign.R == nil { + foreign.R = &tradeR{} + } + foreign.R.ExchangeName = object + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if local.ID == foreign.ExchangeNameID { + local.R.ExchangeNameTrade = foreign + if foreign.R == nil { + foreign.R = &tradeR{} + } + foreign.R.ExchangeName = local + break + } + } + } + + return nil +} + // LoadExchangeNameWithdrawalHistories allows an eager lookup of values, cached into the // loaded structs of the objects. This is for a 1-M or N-M relationship. func (exchangeL) LoadExchangeNameWithdrawalHistories(ctx context.Context, e boil.ContextExecutor, singular bool, maybeExchange interface{}, mods queries.Applicator) error { @@ -631,6 +746,57 @@ func (o *Exchange) SetExchangeNameCandle(ctx context.Context, exec boil.ContextE return nil } +// SetExchangeNameTrade of the exchange to the related item. +// Sets o.R.ExchangeNameTrade to related. +// Adds o to related.R.ExchangeName. +func (o *Exchange) SetExchangeNameTrade(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Trade) error { + var err error + + if insert { + related.ExchangeNameID = o.ID + + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 0, []string{"exchange_name_id"}), + strmangle.WhereClause("\"", "\"", 0, tradePrimaryKeyColumns), + ) + values := []interface{}{o.ID, related.ID} + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) + } + + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + related.ExchangeNameID = o.ID + + } + + if o.R == nil { + o.R = &exchangeR{ + ExchangeNameTrade: related, + } + } else { + o.R.ExchangeNameTrade = related + } + + if related.R == nil { + related.R = &tradeR{ + ExchangeName: o, + } + } else { + related.R.ExchangeName = o + } + return nil +} + // AddExchangeNameWithdrawalHistories adds the given related objects to the existing relationships // of the exchange, optionally inserting them as new records. // Appends related to o.R.ExchangeNameWithdrawalHistories. diff --git a/database/models/sqlite3/exchange_test.go b/database/models/sqlite3/exchange_test.go index f348f874..2a16ca57 100644 --- a/database/models/sqlite3/exchange_test.go +++ b/database/models/sqlite3/exchange_test.go @@ -545,6 +545,57 @@ func testExchangeOneToOneCandleUsingExchangeNameCandle(t *testing.T) { } } +func testExchangeOneToOneTradeUsingExchangeNameTrade(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var foreign Trade + var local Exchange + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &foreign, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err := randomize.Struct(seed, &local, exchangeDBTypes, true, exchangeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Exchange struct: %s", err) + } + + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreign.ExchangeNameID = local.ID + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.ExchangeNameTrade().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if check.ExchangeNameID != foreign.ExchangeNameID { + t.Errorf("want: %v, got %v", foreign.ExchangeNameID, check.ExchangeNameID) + } + + slice := ExchangeSlice{&local} + if err = local.L.LoadExchangeNameTrade(ctx, tx, false, (*[]*Exchange)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeNameTrade == nil { + t.Error("struct should have been eager loaded") + } + + local.R.ExchangeNameTrade = nil + if err = local.L.LoadExchangeNameTrade(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeNameTrade == nil { + t.Error("struct should have been eager loaded") + } +} + func testExchangeOneToOneSetOpCandleUsingExchangeNameCandle(t *testing.T) { var err error @@ -606,6 +657,67 @@ func testExchangeOneToOneSetOpCandleUsingExchangeNameCandle(t *testing.T) { } } } +func testExchangeOneToOneSetOpTradeUsingExchangeNameTrade(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Exchange + var b, c Trade + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, tradeDBTypes, false, strmangle.SetComplement(tradePrimaryKeyColumns, tradeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, tradeDBTypes, false, strmangle.SetComplement(tradePrimaryKeyColumns, tradeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Trade{&b, &c} { + err = a.SetExchangeNameTrade(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.ExchangeNameTrade != x { + t.Error("relationship struct not set to correct value") + } + if x.R.ExchangeName != &a { + t.Error("failed to append to foreign relationship struct") + } + + if a.ID != x.ExchangeNameID { + t.Error("foreign key was wrong value", a.ID) + } + + zero := reflect.Zero(reflect.TypeOf(x.ExchangeNameID)) + reflect.Indirect(reflect.ValueOf(&x.ExchangeNameID)).Set(zero) + + if err = x.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if a.ID != x.ExchangeNameID { + t.Error("foreign key was wrong value", a.ID, x.ExchangeNameID) + } + + if _, err = x.Delete(ctx, tx); err != nil { + t.Fatal("failed to delete x", err) + } + } +} func testExchangeToManyExchangeNameWithdrawalHistories(t *testing.T) { var err error diff --git a/database/models/sqlite3/trade.go b/database/models/sqlite3/trade.go new file mode 100644 index 00000000..7dfac849 --- /dev/null +++ b/database/models/sqlite3/trade.go @@ -0,0 +1,994 @@ +// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package sqlite3 + +import ( + "context" + "database/sql" + "fmt" + "reflect" + "strings" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/thrasher-corp/sqlboiler/boil" + "github.com/thrasher-corp/sqlboiler/queries" + "github.com/thrasher-corp/sqlboiler/queries/qm" + "github.com/thrasher-corp/sqlboiler/queries/qmhelper" + "github.com/thrasher-corp/sqlboiler/strmangle" + "github.com/volatiletech/null" +) + +// Trade is an object representing the database table. +type Trade struct { + ID string `boil:"id" json:"id" toml:"id" yaml:"id"` + ExchangeNameID string `boil:"exchange_name_id" json:"exchange_name_id" toml:"exchange_name_id" yaml:"exchange_name_id"` + Tid null.String `boil:"tid" json:"tid,omitempty" toml:"tid" yaml:"tid,omitempty"` + Base string `boil:"base" json:"base" toml:"base" yaml:"base"` + Quote string `boil:"quote" json:"quote" toml:"quote" yaml:"quote"` + Asset string `boil:"asset" json:"asset" toml:"asset" yaml:"asset"` + Price float64 `boil:"price" json:"price" toml:"price" yaml:"price"` + Amount float64 `boil:"amount" json:"amount" toml:"amount" yaml:"amount"` + Side null.String `boil:"side" json:"side,omitempty" toml:"side" yaml:"side,omitempty"` + Timestamp string `boil:"timestamp" json:"timestamp" toml:"timestamp" yaml:"timestamp"` + + R *tradeR `boil:"-" json:"-" toml:"-" yaml:"-"` + L tradeL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var TradeColumns = struct { + ID string + ExchangeNameID string + Tid string + Base string + Quote string + Asset string + Price string + Amount string + Side string + Timestamp string +}{ + ID: "id", + ExchangeNameID: "exchange_name_id", + Tid: "tid", + Base: "base", + Quote: "quote", + Asset: "asset", + Price: "price", + Amount: "amount", + Side: "side", + Timestamp: "timestamp", +} + +// Generated where +type whereHelpernull_String struct{ field string } + +func (w whereHelpernull_String) EQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, false, x) +} +func (w whereHelpernull_String) NEQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, true, x) +} +func (w whereHelpernull_String) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } +func (w whereHelpernull_String) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } +func (w whereHelpernull_String) LT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpernull_String) LTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpernull_String) GT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpernull_String) GTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} + +var TradeWhere = struct { + ID whereHelperstring + ExchangeNameID whereHelperstring + Tid whereHelpernull_String + Base whereHelperstring + Quote whereHelperstring + Asset whereHelperstring + Price whereHelperfloat64 + Amount whereHelperfloat64 + Side whereHelpernull_String + Timestamp whereHelperstring +}{ + ID: whereHelperstring{field: "\"trade\".\"id\""}, + ExchangeNameID: whereHelperstring{field: "\"trade\".\"exchange_name_id\""}, + Tid: whereHelpernull_String{field: "\"trade\".\"tid\""}, + Base: whereHelperstring{field: "\"trade\".\"base\""}, + Quote: whereHelperstring{field: "\"trade\".\"quote\""}, + Asset: whereHelperstring{field: "\"trade\".\"asset\""}, + Price: whereHelperfloat64{field: "\"trade\".\"price\""}, + Amount: whereHelperfloat64{field: "\"trade\".\"amount\""}, + Side: whereHelpernull_String{field: "\"trade\".\"side\""}, + Timestamp: whereHelperstring{field: "\"trade\".\"timestamp\""}, +} + +// TradeRels is where relationship names are stored. +var TradeRels = struct { + ExchangeName string +}{ + ExchangeName: "ExchangeName", +} + +// tradeR is where relationships are stored. +type tradeR struct { + ExchangeName *Exchange +} + +// NewStruct creates a new relationship struct +func (*tradeR) NewStruct() *tradeR { + return &tradeR{} +} + +// tradeL is where Load methods for each relationship are stored. +type tradeL struct{} + +var ( + tradeAllColumns = []string{"id", "exchange_name_id", "tid", "base", "quote", "asset", "price", "amount", "side", "timestamp"} + tradeColumnsWithoutDefault = []string{"id", "exchange_name_id", "tid", "base", "quote", "asset", "price", "amount", "side", "timestamp"} + tradeColumnsWithDefault = []string{} + tradePrimaryKeyColumns = []string{"id"} +) + +type ( + // TradeSlice is an alias for a slice of pointers to Trade. + // This should generally be used opposed to []Trade. + TradeSlice []*Trade + // TradeHook is the signature for custom Trade hook methods + TradeHook func(context.Context, boil.ContextExecutor, *Trade) error + + tradeQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + tradeType = reflect.TypeOf(&Trade{}) + tradeMapping = queries.MakeStructMapping(tradeType) + tradePrimaryKeyMapping, _ = queries.BindMapping(tradeType, tradeMapping, tradePrimaryKeyColumns) + tradeInsertCacheMut sync.RWMutex + tradeInsertCache = make(map[string]insertCache) + tradeUpdateCacheMut sync.RWMutex + tradeUpdateCache = make(map[string]updateCache) + tradeUpsertCacheMut sync.RWMutex + tradeUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +var tradeBeforeInsertHooks []TradeHook +var tradeBeforeUpdateHooks []TradeHook +var tradeBeforeDeleteHooks []TradeHook +var tradeBeforeUpsertHooks []TradeHook + +var tradeAfterInsertHooks []TradeHook +var tradeAfterSelectHooks []TradeHook +var tradeAfterUpdateHooks []TradeHook +var tradeAfterDeleteHooks []TradeHook +var tradeAfterUpsertHooks []TradeHook + +// doBeforeInsertHooks executes all "before insert" hooks. +func (o *Trade) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpdateHooks executes all "before Update" hooks. +func (o *Trade) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeDeleteHooks executes all "before Delete" hooks. +func (o *Trade) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpsertHooks executes all "before Upsert" hooks. +func (o *Trade) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeBeforeUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterInsertHooks executes all "after Insert" hooks. +func (o *Trade) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterSelectHooks executes all "after Select" hooks. +func (o *Trade) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterSelectHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpdateHooks executes all "after Update" hooks. +func (o *Trade) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterDeleteHooks executes all "after Delete" hooks. +func (o *Trade) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpsertHooks executes all "after Upsert" hooks. +func (o *Trade) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range tradeAfterUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// AddTradeHook registers your hook function for all future operations. +func AddTradeHook(hookPoint boil.HookPoint, tradeHook TradeHook) { + switch hookPoint { + case boil.BeforeInsertHook: + tradeBeforeInsertHooks = append(tradeBeforeInsertHooks, tradeHook) + case boil.BeforeUpdateHook: + tradeBeforeUpdateHooks = append(tradeBeforeUpdateHooks, tradeHook) + case boil.BeforeDeleteHook: + tradeBeforeDeleteHooks = append(tradeBeforeDeleteHooks, tradeHook) + case boil.BeforeUpsertHook: + tradeBeforeUpsertHooks = append(tradeBeforeUpsertHooks, tradeHook) + case boil.AfterInsertHook: + tradeAfterInsertHooks = append(tradeAfterInsertHooks, tradeHook) + case boil.AfterSelectHook: + tradeAfterSelectHooks = append(tradeAfterSelectHooks, tradeHook) + case boil.AfterUpdateHook: + tradeAfterUpdateHooks = append(tradeAfterUpdateHooks, tradeHook) + case boil.AfterDeleteHook: + tradeAfterDeleteHooks = append(tradeAfterDeleteHooks, tradeHook) + case boil.AfterUpsertHook: + tradeAfterUpsertHooks = append(tradeAfterUpsertHooks, tradeHook) + } +} + +// One returns a single trade record from the query. +func (q tradeQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Trade, error) { + o := &Trade{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(ctx, exec, o) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "sqlite3: failed to execute a one query for trade") + } + + if err := o.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + + return o, nil +} + +// All returns all Trade records from the query. +func (q tradeQuery) All(ctx context.Context, exec boil.ContextExecutor) (TradeSlice, error) { + var o []*Trade + + err := q.Bind(ctx, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "sqlite3: failed to assign all query results to Trade slice") + } + + if len(tradeAfterSelectHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + } + } + + return o, nil +} + +// Count returns the count of all Trade records in the query. +func (q tradeQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: failed to count trade rows") + } + + return count, nil +} + +// Exists checks if the row exists in the table. +func (q tradeQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "sqlite3: failed to check if trade exists") + } + + return count > 0, nil +} + +// ExchangeName pointed to by the foreign key. +func (o *Trade) ExchangeName(mods ...qm.QueryMod) exchangeQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.ExchangeNameID), + } + + queryMods = append(queryMods, mods...) + + query := Exchanges(queryMods...) + queries.SetFrom(query.Query, "\"exchange\"") + + return query +} + +// LoadExchangeName allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (tradeL) LoadExchangeName(ctx context.Context, e boil.ContextExecutor, singular bool, maybeTrade interface{}, mods queries.Applicator) error { + var slice []*Trade + var object *Trade + + if singular { + object = maybeTrade.(*Trade) + } else { + slice = *maybeTrade.(*[]*Trade) + } + + args := make([]interface{}, 0, 1) + if singular { + if object.R == nil { + object.R = &tradeR{} + } + args = append(args, object.ExchangeNameID) + + } else { + Outer: + for _, obj := range slice { + if obj.R == nil { + obj.R = &tradeR{} + } + + for _, a := range args { + if a == obj.ExchangeNameID { + continue Outer + } + } + + args = append(args, obj.ExchangeNameID) + + } + } + + if len(args) == 0 { + return nil + } + + query := NewQuery(qm.From(`exchange`), qm.WhereIn(`exchange.id in ?`, args...)) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Exchange") + } + + var resultSlice []*Exchange + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Exchange") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for exchange") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for exchange") + } + + if len(tradeAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.ExchangeName = foreign + if foreign.R == nil { + foreign.R = &exchangeR{} + } + foreign.R.ExchangeNameTrade = object + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if local.ExchangeNameID == foreign.ID { + local.R.ExchangeName = foreign + if foreign.R == nil { + foreign.R = &exchangeR{} + } + foreign.R.ExchangeNameTrade = local + break + } + } + } + + return nil +} + +// SetExchangeName of the trade to the related item. +// Sets o.R.ExchangeName to related. +// Adds o to related.R.ExchangeNameTrade. +func (o *Trade) SetExchangeName(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Exchange) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 0, []string{"exchange_name_id"}), + strmangle.WhereClause("\"", "\"", 0, tradePrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, updateQuery) + fmt.Fprintln(boil.DebugWriter, values) + } + + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + o.ExchangeNameID = related.ID + if o.R == nil { + o.R = &tradeR{ + ExchangeName: related, + } + } else { + o.R.ExchangeName = related + } + + if related.R == nil { + related.R = &exchangeR{ + ExchangeNameTrade: o, + } + } else { + related.R.ExchangeNameTrade = o + } + + return nil +} + +// Trades retrieves all the records using an executor. +func Trades(mods ...qm.QueryMod) tradeQuery { + mods = append(mods, qm.From("\"trade\"")) + return tradeQuery{NewQuery(mods...)} +} + +// FindTrade retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindTrade(ctx context.Context, exec boil.ContextExecutor, iD string, selectCols ...string) (*Trade, error) { + tradeObj := &Trade{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from \"trade\" where \"id\"=?", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(ctx, exec, tradeObj) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "sqlite3: unable to select from trade") + } + + return tradeObj, nil +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Trade) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { + if o == nil { + return errors.New("sqlite3: no trade provided for insertion") + } + + var err error + + if err := o.doBeforeInsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(tradeColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + tradeInsertCacheMut.RLock() + cache, cached := tradeInsertCache[key] + tradeInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + tradeAllColumns, + tradeColumnsWithDefault, + tradeColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(tradeType, tradeMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(tradeType, tradeMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO \"trade\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO \"trade\" () VALUES ()%s%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + cache.retQuery = fmt.Sprintf("SELECT \"%s\" FROM \"trade\" WHERE %s", strings.Join(returnColumns, "\",\""), strmangle.WhereClause("\"", "\"", 0, tradePrimaryKeyColumns)) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, vals) + } + + _, err = exec.ExecContext(ctx, cache.query, vals...) + + if err != nil { + return errors.Wrap(err, "sqlite3: unable to insert into trade") + } + + var identifierCols []interface{} + + if len(cache.retMapping) == 0 { + goto CacheNoHooks + } + + identifierCols = []interface{}{ + o.ID, + } + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.retQuery) + fmt.Fprintln(boil.DebugWriter, identifierCols...) + } + + err = exec.QueryRowContext(ctx, cache.retQuery, identifierCols...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + if err != nil { + return errors.Wrap(err, "sqlite3: unable to populate default values for trade") + } + +CacheNoHooks: + if !cached { + tradeInsertCacheMut.Lock() + tradeInsertCache[key] = cache + tradeInsertCacheMut.Unlock() + } + + return o.doAfterInsertHooks(ctx, exec) +} + +// Update uses an executor to update the Trade. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Trade) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) { + var err error + if err = o.doBeforeUpdateHooks(ctx, exec); err != nil { + return 0, err + } + key := makeCacheKey(columns, nil) + tradeUpdateCacheMut.RLock() + cache, cached := tradeUpdateCache[key] + tradeUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + tradeAllColumns, + tradePrimaryKeyColumns, + ) + + if len(wl) == 0 { + return 0, errors.New("sqlite3: unable to update trade, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 0, wl), + strmangle.WhereClause("\"", "\"", 0, tradePrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(tradeType, tradeMapping, append(wl, tradePrimaryKeyColumns...)) + if err != nil { + return 0, err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, cache.query) + fmt.Fprintln(boil.DebugWriter, values) + } + + var result sql.Result + result, err = exec.ExecContext(ctx, cache.query, values...) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to update trade row") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by update for trade") + } + + if !cached { + tradeUpdateCacheMut.Lock() + tradeUpdateCache[key] = cache + tradeUpdateCacheMut.Unlock() + } + + return rowsAff, o.doAfterUpdateHooks(ctx, exec) +} + +// UpdateAll updates all rows with the specified column values. +func (q tradeQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + queries.SetUpdate(q.Query, cols) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to update all for trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected for trade") + } + + return rowsAff, nil +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o TradeSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + ln := int64(len(o)) + if ln == 0 { + return 0, nil + } + + if len(cols) == 0 { + return 0, errors.New("sqlite3: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE \"trade\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 0, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, tradePrimaryKeyColumns, len(o))) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to update all in trade slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to retrieve rows affected all in update all trade") + } + return rowsAff, nil +} + +// Delete deletes a single Trade record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Trade) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if o == nil { + return 0, errors.New("sqlite3: no Trade provided for delete") + } + + if err := o.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), tradePrimaryKeyMapping) + sql := "DELETE FROM \"trade\" WHERE \"id\"=?" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args...) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to delete from trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by delete for trade") + } + + if err := o.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + return rowsAff, nil +} + +// DeleteAll deletes all matching rows. +func (q tradeQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if q.Query == nil { + return 0, errors.New("sqlite3: no tradeQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to delete all from trade") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for trade") + } + + return rowsAff, nil +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o TradeSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if len(o) == 0 { + return 0, nil + } + + if len(tradeBeforeDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM \"trade\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, tradePrimaryKeyColumns, len(o)) + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, args) + } + + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "sqlite3: unable to delete all from trade slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "sqlite3: failed to get rows affected by deleteall for trade") + } + + if len(tradeAfterDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + return rowsAff, nil +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Trade) Reload(ctx context.Context, exec boil.ContextExecutor) error { + ret, err := FindTrade(ctx, exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *TradeSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := TradeSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), tradePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT \"trade\".* FROM \"trade\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 0, tradePrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(ctx, exec, &slice) + if err != nil { + return errors.Wrap(err, "sqlite3: unable to reload all in TradeSlice") + } + + *o = slice + + return nil +} + +// TradeExists checks if the Trade row exists. +func TradeExists(ctx context.Context, exec boil.ContextExecutor, iD string) (bool, error) { + var exists bool + sql := "select exists(select 1 from \"trade\" where \"id\"=? limit 1)" + + if boil.DebugMode { + fmt.Fprintln(boil.DebugWriter, sql) + fmt.Fprintln(boil.DebugWriter, iD) + } + + row := exec.QueryRowContext(ctx, sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "sqlite3: unable to check if trade exists") + } + + return exists, nil +} diff --git a/database/models/sqlite3/trade_test.go b/database/models/sqlite3/trade_test.go new file mode 100644 index 00000000..9b9871e2 --- /dev/null +++ b/database/models/sqlite3/trade_test.go @@ -0,0 +1,793 @@ +// Code generated by SQLBoiler 3.5.0-gct (https://github.com/thrasher-corp/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package sqlite3 + +import ( + "bytes" + "context" + "reflect" + "testing" + + "github.com/thrasher-corp/sqlboiler/boil" + "github.com/thrasher-corp/sqlboiler/queries" + "github.com/thrasher-corp/sqlboiler/randomize" + "github.com/thrasher-corp/sqlboiler/strmangle" +) + +var ( + // Relationships sometimes use the reflection helper queries.Equal/queries.Assign + // so force a package dependency in case they don't. + _ = queries.Equal +) + +func testTrades(t *testing.T) { + t.Parallel() + + query := Trades() + + if query.Query == nil { + t.Error("expected a query, got nothing") + } +} + +func testTradesDelete(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := o.Delete(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesQueryDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := Trades().DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesSliceDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := TradeSlice{o} + + if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testTradesExists(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + e, err := TradeExists(ctx, tx, o.ID) + if err != nil { + t.Errorf("Unable to check if Trade exists: %s", err) + } + if !e { + t.Errorf("Expected TradeExists to return true, but got false.") + } +} + +func testTradesFind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + tradeFound, err := FindTrade(ctx, tx, o.ID) + if err != nil { + t.Error(err) + } + + if tradeFound == nil { + t.Error("want a record, got nil") + } +} + +func testTradesBind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = Trades().Bind(ctx, tx, o); err != nil { + t.Error(err) + } +} + +func testTradesOne(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if x, err := Trades().One(ctx, tx); err != nil { + t.Error(err) + } else if x == nil { + t.Error("expected to get a non nil record") + } +} + +func testTradesAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + tradeOne := &Trade{} + tradeTwo := &Trade{} + if err = randomize.Struct(seed, tradeOne, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err = randomize.Struct(seed, tradeTwo, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = tradeOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = tradeTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Trades().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 2 { + t.Error("want 2 records, got:", len(slice)) + } +} + +func testTradesCount(t *testing.T) { + t.Parallel() + + var err error + seed := randomize.NewSeed() + tradeOne := &Trade{} + tradeTwo := &Trade{} + if err = randomize.Struct(seed, tradeOne, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err = randomize.Struct(seed, tradeTwo, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = tradeOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = tradeTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 2 { + t.Error("want 2 records, got:", count) + } +} + +func tradeBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func tradeAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Trade) error { + *o = Trade{} + return nil +} + +func testTradesHooks(t *testing.T) { + t.Parallel() + + var err error + + ctx := context.Background() + empty := &Trade{} + o := &Trade{} + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, o, tradeDBTypes, false); err != nil { + t.Errorf("Unable to randomize Trade object: %s", err) + } + + AddTradeHook(boil.BeforeInsertHook, tradeBeforeInsertHook) + if err = o.doBeforeInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o) + } + tradeBeforeInsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterInsertHook, tradeAfterInsertHook) + if err = o.doAfterInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o) + } + tradeAfterInsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterSelectHook, tradeAfterSelectHook) + if err = o.doAfterSelectHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterSelectHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o) + } + tradeAfterSelectHooks = []TradeHook{} + + AddTradeHook(boil.BeforeUpdateHook, tradeBeforeUpdateHook) + if err = o.doBeforeUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o) + } + tradeBeforeUpdateHooks = []TradeHook{} + + AddTradeHook(boil.AfterUpdateHook, tradeAfterUpdateHook) + if err = o.doAfterUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o) + } + tradeAfterUpdateHooks = []TradeHook{} + + AddTradeHook(boil.BeforeDeleteHook, tradeBeforeDeleteHook) + if err = o.doBeforeDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o) + } + tradeBeforeDeleteHooks = []TradeHook{} + + AddTradeHook(boil.AfterDeleteHook, tradeAfterDeleteHook) + if err = o.doAfterDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o) + } + tradeAfterDeleteHooks = []TradeHook{} + + AddTradeHook(boil.BeforeUpsertHook, tradeBeforeUpsertHook) + if err = o.doBeforeUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o) + } + tradeBeforeUpsertHooks = []TradeHook{} + + AddTradeHook(boil.AfterUpsertHook, tradeAfterUpsertHook) + if err = o.doAfterUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o) + } + tradeAfterUpsertHooks = []TradeHook{} +} + +func testTradesInsert(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testTradesInsertWhitelist(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Whitelist(tradeColumnsWithoutDefault...)); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testTradeToOneExchangeUsingExchangeName(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Trade + var foreign Exchange + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, tradeDBTypes, false, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, exchangeDBTypes, false, exchangeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Exchange struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + local.ExchangeNameID = foreign.ID + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.ExchangeName().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if check.ID != foreign.ID { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + slice := TradeSlice{&local} + if err = local.L.LoadExchangeName(ctx, tx, false, (*[]*Trade)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeName == nil { + t.Error("struct should have been eager loaded") + } + + local.R.ExchangeName = nil + if err = local.L.LoadExchangeName(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.ExchangeName == nil { + t.Error("struct should have been eager loaded") + } +} + +func testTradeToOneSetOpExchangeUsingExchangeName(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Trade + var b, c Exchange + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, tradeDBTypes, false, strmangle.SetComplement(tradePrimaryKeyColumns, tradeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, exchangeDBTypes, false, strmangle.SetComplement(exchangePrimaryKeyColumns, exchangeColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Exchange{&b, &c} { + err = a.SetExchangeName(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.ExchangeName != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.ExchangeNameTrade != &a { + t.Error("failed to append to foreign relationship struct") + } + if a.ExchangeNameID != x.ID { + t.Error("foreign key was wrong value", a.ExchangeNameID) + } + + zero := reflect.Zero(reflect.TypeOf(a.ExchangeNameID)) + reflect.Indirect(reflect.ValueOf(&a.ExchangeNameID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if a.ExchangeNameID != x.ID { + t.Error("foreign key was wrong value", a.ExchangeNameID, x.ID) + } + } +} + +func testTradesReload(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = o.Reload(ctx, tx); err != nil { + t.Error(err) + } +} + +func testTradesReloadAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := TradeSlice{o} + + if err = slice.ReloadAll(ctx, tx); err != nil { + t.Error(err) + } +} + +func testTradesSelect(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Trades().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 1 { + t.Error("want one record, got:", len(slice)) + } +} + +var ( + tradeDBTypes = map[string]string{`ID`: `TEXT`, `ExchangeNameID`: `UUID`, `Tid`: `TEXT`, `Base`: `TEXT`, `Quote`: `TEXT`, `Asset`: `TEXT`, `Price`: `REAL`, `Amount`: `REAL`, `Side`: `TEXT`, `Timestamp`: `TIMESTAMP`} + _ = bytes.MinRead +) + +func testTradesUpdate(t *testing.T) { + t.Parallel() + + if 0 == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with no primary key columns") + } + if len(tradeAllColumns) == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only affect one row but affected", rowsAff) + } +} + +func testTradesSliceUpdateAll(t *testing.T) { + t.Parallel() + + if len(tradeAllColumns) == len(tradePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Trade{} + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradeColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Trades().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, tradeDBTypes, true, tradePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Trade struct: %s", err) + } + + // Remove Primary keys and unique columns from what we plan to update + var fields []string + if strmangle.StringSliceMatch(tradeAllColumns, tradePrimaryKeyColumns) { + fields = tradeAllColumns + } else { + fields = strmangle.SetComplement( + tradeAllColumns, + tradePrimaryKeyColumns, + ) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + typ := reflect.TypeOf(o).Elem() + n := typ.NumField() + + updateMap := M{} + for _, col := range fields { + for i := 0; i < n; i++ { + f := typ.Field(i) + if f.Tag.Get("boil") == col { + updateMap[col] = value.Field(i).Interface() + } + } + } + + slice := TradeSlice{o} + if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("wanted one record updated but got", rowsAff) + } +} diff --git a/database/models/sqlite3/withdrawal_crypto.go b/database/models/sqlite3/withdrawal_crypto.go index 43bfac93..f5ee7e05 100644 --- a/database/models/sqlite3/withdrawal_crypto.go +++ b/database/models/sqlite3/withdrawal_crypto.go @@ -49,29 +49,6 @@ var WithdrawalCryptoColumns = struct { // Generated where -type whereHelpernull_String struct{ field string } - -func (w whereHelpernull_String) EQ(x null.String) qm.QueryMod { - return qmhelper.WhereNullEQ(w.field, false, x) -} -func (w whereHelpernull_String) NEQ(x null.String) qm.QueryMod { - return qmhelper.WhereNullEQ(w.field, true, x) -} -func (w whereHelpernull_String) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } -func (w whereHelpernull_String) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } -func (w whereHelpernull_String) LT(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LT, x) -} -func (w whereHelpernull_String) LTE(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LTE, x) -} -func (w whereHelpernull_String) GT(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GT, x) -} -func (w whereHelpernull_String) GTE(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GTE, x) -} - var WithdrawalCryptoWhere = struct { ID whereHelperint64 Address whereHelperstring diff --git a/database/repository/candle/candle.go b/database/repository/candle/candle.go index c6c961db..7e277650 100644 --- a/database/repository/candle/candle.go +++ b/database/repository/candle/candle.go @@ -33,8 +33,7 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star qm.Where("base = ?", strings.ToUpper(base)), qm.Where("quote = ?", strings.ToUpper(quote)), qm.Where("interval = ?", interval), - qm.Where("asset = ?", asset), - qm.Where("timestamp between ? and ?", start.UTC(), end.UTC()), + qm.Where("asset = ?", strings.ToLower(asset)), } exchangeUUID, errS := exchange.UUIDByName(exchangeName) @@ -42,8 +41,8 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star return out, errS } queries = append(queries, qm.Where("exchange_name_id = ?", exchangeUUID.String())) - if repository.GetSQLDialect() == database.DBSQLite3 { + queries = append(queries, qm.Where("timestamp between ? and ?", start.UTC().Format(time.RFC3339), end.UTC().Format(time.RFC3339))) retCandle, errC := modelSQLite.Candles(queries...).All(context.Background(), database.DB.SQL) if errC != nil { return out, errC @@ -63,6 +62,7 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star }) } } else { + queries = append(queries, qm.Where("timestamp between ? and ?", start.UTC(), end.UTC())) retCandle, errC := modelPSQL.Candles(queries...).All(context.Background(), database.DB.SQL) if errC != nil { return out, errC @@ -91,6 +91,86 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star return out, err } +// DeleteCandles will delete all existing matching candles +func DeleteCandles(in *Item) (int64, error) { + if database.DB.SQL == nil { + return 0, database.ErrDatabaseSupportDisabled + } + if len(in.Candles) < 1 { + return 0, errNoCandleData + } + + ctx := context.Background() + queries := []qm.QueryMod{ + qm.Where("base = ?", strings.ToUpper(in.Base)), + qm.Where("quote = ?", strings.ToUpper(in.Quote)), + qm.Where("interval = ?", in.Interval), + qm.Where("asset = ?", strings.ToLower(in.Asset)), + qm.Where("exchange_name_id = ?", in.ExchangeID), + } + if repository.GetSQLDialect() == database.DBSQLite3 { + queries = append(queries, qm.Where("timestamp between ? and ?", in.Candles[0].Timestamp.UTC().Format(time.RFC3339), in.Candles[len(in.Candles)-1].Timestamp.UTC().Format(time.RFC3339))) + return deleteSQLite(ctx, queries) + } + + queries = append(queries, qm.Where("timestamp between ? and ?", in.Candles[0].Timestamp.UTC(), in.Candles[len(in.Candles)-1].Timestamp.UTC())) + return deletePostgres(ctx, queries) +} + +func deleteSQLite(ctx context.Context, queries []qm.QueryMod) (int64, error) { + retCandle, err := modelSQLite.Candles(queries...).All(context.Background(), database.DB.SQL) + if err != nil { + return 0, err + } + var tx *sql.Tx + tx, err = database.DB.SQL.BeginTx(ctx, nil) + if err != nil { + return 0, err + } + var totalDeleted int64 + totalDeleted, err = retCandle.DeleteAll(ctx, tx) + if err != nil { + errRB := tx.Rollback() + if errRB != nil { + log.Errorln(log.DatabaseMgr, errRB) + } + return 0, err + } + + err = tx.Commit() + if err != nil { + return 0, err + } + return totalDeleted, nil +} + +func deletePostgres(ctx context.Context, queries []qm.QueryMod) (int64, error) { + retCandle, err := modelPSQL.Candles(queries...).All(context.Background(), database.DB.SQL) + if err != nil { + return 0, err + } + var tx *sql.Tx + tx, err = database.DB.SQL.BeginTx(ctx, nil) + if err != nil { + return 0, err + } + var totalDeleted int64 + totalDeleted, err = retCandle.DeleteAll(ctx, tx) + if err != nil { + errRB := tx.Rollback() + if errRB != nil { + log.Errorln(log.DatabaseMgr, errRB) + } + return 0, err + } + + err = tx.Commit() + if err != nil { + return 0, err + } + return totalDeleted, nil +} + // Insert series of candles func Insert(in *Item) (uint64, error) { if database.DB.SQL == nil { @@ -136,7 +216,7 @@ func insertSQLite(ctx context.Context, tx *sql.Tx, in *Item) (uint64, error) { Base: strings.ToUpper(in.Base), Quote: strings.ToUpper(in.Quote), Interval: strconv.FormatInt(in.Interval, 10), - Asset: in.Asset, + Asset: strings.ToLower(in.Asset), Timestamp: in.Candles[x].Timestamp.UTC().Format(time.RFC3339), Open: in.Candles[x].Open, High: in.Candles[x].High, @@ -168,7 +248,7 @@ func insertPostgresSQL(ctx context.Context, tx *sql.Tx, in *Item) (uint64, error Base: strings.ToUpper(in.Base), Quote: strings.ToUpper(in.Quote), Interval: in.Interval, - Asset: in.Asset, + Asset: strings.ToLower(in.Asset), Timestamp: in.Candles[x].Timestamp, Open: in.Candles[x].Open, High: in.Candles[x].High, diff --git a/database/repository/candle/candle_test.go b/database/repository/candle/candle_test.go index 94b74fbb..cb9b6c23 100644 --- a/database/repository/candle/candle_test.go +++ b/database/repository/candle/candle_test.go @@ -105,8 +105,17 @@ func TestInsert(t *testing.T) { } if r != 365 { - t.Fatalf("unexpected number inserted: %v", r) + t.Errorf("unexpected number inserted: %v", r) } + + d, err := DeleteCandles(&data) + if err != nil { + t.Fatal(err) + } + if d != 365 { + t.Errorf("unexpected number deleted: %v", d) + } + err = testhelpers.CloseDatabase(dbConn) if err != nil { t.Error(err) diff --git a/database/repository/candle/candle_types.go b/database/repository/candle/candle_types.go index 09477b56..fd0c7e9f 100644 --- a/database/repository/candle/candle_types.go +++ b/database/repository/candle/candle_types.go @@ -10,7 +10,7 @@ const ( ) var ( - errInvalidInput = errors.New("exchange, base , quote, asset, interval, start & end cannot be empty") + errInvalidInput = errors.New("exchange, base, quote, asset, interval, start & end cannot be empty") errNoCandleData = errors.New("no candle data provided") ) diff --git a/database/repository/exchange/exchange.go b/database/repository/exchange/exchange.go index c2d736e6..2a69cd07 100644 --- a/database/repository/exchange/exchange.go +++ b/database/repository/exchange/exchange.go @@ -72,7 +72,6 @@ func Insert(in Details) error { if err != nil { return err } - if repository.GetSQLDialect() == database.DBSQLite3 { err = insertSQLite(ctx, tx, []Details{in}) } else { @@ -139,7 +138,7 @@ func insertSQLite(ctx context.Context, tx *sql.Tx, in []Details) (err error) { return errUUID } var tempInsert = modelSQLite.Exchange{ - Name: in[x].Name, + Name: strings.ToLower(in[x].Name), ID: tempUUID.String(), } @@ -159,7 +158,7 @@ func insertSQLite(ctx context.Context, tx *sql.Tx, in []Details) (err error) { func insertPostgresql(ctx context.Context, tx *sql.Tx, in []Details) (err error) { for x := range in { var tempInsert = modelPSQL.Exchange{ - Name: in[x].Name, + Name: strings.ToLower(in[x].Name), } err = tempInsert.Upsert(ctx, tx, true, []string{"name"}, boil.Infer(), boil.Infer()) diff --git a/database/repository/trade/trade.go b/database/repository/trade/trade.go new file mode 100644 index 00000000..50285da9 --- /dev/null +++ b/database/repository/trade/trade.go @@ -0,0 +1,359 @@ +package trade + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strings" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/database" + modelPSQL "github.com/thrasher-corp/gocryptotrader/database/models/postgres" + modelSQLite "github.com/thrasher-corp/gocryptotrader/database/models/sqlite3" + "github.com/thrasher-corp/gocryptotrader/database/repository" + "github.com/thrasher-corp/gocryptotrader/database/repository/exchange" + "github.com/thrasher-corp/gocryptotrader/log" + "github.com/thrasher-corp/sqlboiler/boil" + "github.com/thrasher-corp/sqlboiler/queries/qm" +) + +// Insert saves trade data to the database +func Insert(trades ...Data) error { + for i := range trades { + if trades[i].ExchangeNameID == "" && trades[i].Exchange != "" { + exchangeUUID, err := exchange.UUIDByName(trades[i].Exchange) + if err != nil { + return err + } + trades[i].ExchangeNameID = exchangeUUID.String() + } else if trades[i].ExchangeNameID == "" && trades[i].Exchange == "" { + return errors.New("exchange name/uuid not set, cannot insert") + } + } + + ctx := context.Background() + ctx = boil.SkipTimestamps(ctx) + + tx, err := database.DB.SQL.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("beginTx %w", err) + } + defer func() { + if err != nil { + errRB := tx.Rollback() + if errRB != nil { + log.Errorf(log.DatabaseMgr, "Insert tx.Rollback %v", errRB) + } + } + }() + + if repository.GetSQLDialect() == database.DBSQLite3 || repository.GetSQLDialect() == database.DBSQLite { + err = insertSQLite(ctx, tx, trades...) + } else { + err = insertPostgres(ctx, tx, trades...) + } + if err != nil { + return err + } + + return tx.Commit() +} + +func insertSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error { + for i := range trades { + if trades[i].ID == "" { + freshUUID, err := uuid.NewV4() + if err != nil { + return err + } + trades[i].ID = freshUUID.String() + } + var tempEvent = modelSQLite.Trade{ + ID: trades[i].ID, + ExchangeNameID: trades[i].ExchangeNameID, + Base: strings.ToUpper(trades[i].Base), + Quote: strings.ToUpper(trades[i].Quote), + Asset: strings.ToLower(trades[i].AssetType), + Price: trades[i].Price, + Amount: trades[i].Amount, + Timestamp: trades[i].Timestamp.UTC().Format(time.RFC3339), + } + if trades[i].Side != "" { + tempEvent.Side.SetValid(strings.ToUpper(trades[i].Side)) + } + if trades[i].TID != "" { + tempEvent.Tid.SetValid(trades[i].TID) + } + err := tempEvent.Insert(ctx, tx, boil.Infer()) + if err != nil { + return err + } + } + + return nil +} + +func insertPostgres(ctx context.Context, tx *sql.Tx, trades ...Data) error { + var err error + for i := range trades { + if trades[i].ID == "" { + var freshUUID uuid.UUID + freshUUID, err = uuid.NewV4() + if err != nil { + return err + } + trades[i].ID = freshUUID.String() + } + var tempEvent = modelPSQL.Trade{ + ExchangeNameID: trades[i].ExchangeNameID, + Base: strings.ToUpper(trades[i].Base), + Quote: strings.ToUpper(trades[i].Quote), + Asset: strings.ToLower(trades[i].AssetType), + Price: trades[i].Price, + Amount: trades[i].Amount, + Timestamp: trades[i].Timestamp.UTC(), + ID: trades[i].ID, + } + if trades[i].Side != "" { + tempEvent.Side.SetValid(strings.ToUpper(trades[i].Side)) + } + if trades[i].TID != "" { + tempEvent.Tid.SetValid(trades[i].TID) + } + + err = tempEvent.Upsert(ctx, tx, false, nil, boil.Infer(), boil.Infer()) + if err != nil { + return err + } + } + + return nil +} + +// GetByUUID returns a trade by its unique ID +func GetByUUID(uuid string) (td Data, err error) { + if repository.GetSQLDialect() == database.DBSQLite3 || repository.GetSQLDialect() == database.DBSQLite { + td, err = getByUUIDSQLite(uuid) + if err != nil { + return td, fmt.Errorf("trade.Get getByUUIDSQLite %w", err) + } + } else { + td, err = getByUUIDPostgres(uuid) + if err != nil { + return td, fmt.Errorf("trade.Get getByUUIDPostgres %w", err) + } + } + + return td, nil +} + +func getByUUIDSQLite(uuid string) (Data, error) { + var td Data + var ts time.Time + query := modelSQLite.Trades(qm.Where("id = ?", uuid)) + result, err := query.One(context.Background(), database.DB.SQL) + if err != nil { + return td, err + } + ts, err = time.Parse(time.RFC3339, result.Timestamp) + if err != nil { + return td, err + } + + td = Data{ + ID: result.ID, + Exchange: result.ExchangeNameID, + Base: strings.ToUpper(result.Base), + Quote: strings.ToUpper(result.Quote), + AssetType: strings.ToLower(result.Asset), + Price: result.Price, + Amount: result.Amount, + Timestamp: ts, + } + if result.Side.Valid { + td.Side = result.Side.String + } + return td, nil +} + +func getByUUIDPostgres(uuid string) (td Data, err error) { + query := modelPSQL.Trades(qm.Where("id = ?", uuid)) + var result *modelPSQL.Trade + result, err = query.One(context.Background(), database.DB.SQL) + if err != nil { + return td, err + } + + td = Data{ + ID: result.ID, + Timestamp: result.Timestamp, + Exchange: result.ExchangeNameID, + Base: strings.ToUpper(result.Base), + Quote: strings.ToUpper(result.Quote), + AssetType: strings.ToLower(result.Asset), + Price: result.Price, + Amount: result.Amount, + } + if result.Side.Valid { + td.Side = result.Side.String + } + return td, nil +} + +// GetInRange returns all trades by an exchange in a date range +func GetInRange(exchangeName, assetType, base, quote string, startDate, endDate time.Time) (td []Data, err error) { + if repository.GetSQLDialect() == database.DBSQLite3 || repository.GetSQLDialect() == database.DBSQLite { + td, err = getInRangeSQLite(exchangeName, assetType, base, quote, startDate, endDate) + if err != nil { + return td, fmt.Errorf("trade.GetByExchangeInRange getInRangeSQLite %w", err) + } + } else { + td, err = getInRangePostgres(exchangeName, assetType, base, quote, startDate, endDate) + if err != nil { + return td, fmt.Errorf("trade.GetByExchangeInRange getInRangePostgres %w", err) + } + } + + return td, nil +} + +func getInRangeSQLite(exchangeName, assetType, base, quote string, startDate, endDate time.Time) (td []Data, err error) { + var exchangeUUID uuid.UUID + exchangeUUID, err = exchange.UUIDByName(exchangeName) + if err != nil { + return nil, err + } + wheres := map[string]interface{}{ + "exchange_name_id": exchangeUUID, + "asset": strings.ToLower(assetType), + "base": strings.ToUpper(base), + "quote": strings.ToUpper(quote), + } + q := generateQuery(wheres, startDate, endDate) + query := modelSQLite.Trades(q...) + var result []*modelSQLite.Trade + result, err = query.All(context.Background(), database.DB.SQL) + if err != nil { + return td, err + } + for i := range result { + ts, err := time.Parse(time.RFC3339, result[i].Timestamp) + if err != nil { + return td, err + } + t := Data{ + ID: result[i].ID, + Timestamp: ts, + Exchange: strings.ToLower(exchangeName), + Base: strings.ToUpper(result[i].Base), + Quote: strings.ToUpper(result[i].Quote), + AssetType: strings.ToLower(result[i].Asset), + Price: result[i].Price, + Amount: result[i].Amount, + } + if result[i].Side.Valid { + t.Side = result[i].Side.String + } + td = append(td, t) + } + return td, nil +} + +func getInRangePostgres(exchangeName, assetType, base, quote string, startDate, endDate time.Time) (td []Data, err error) { + var exchangeUUID uuid.UUID + exchangeUUID, err = exchange.UUIDByName(exchangeName) + if err != nil { + return nil, err + } + wheres := map[string]interface{}{ + "exchange_name_id": exchangeUUID, + "asset": strings.ToLower(assetType), + "base": strings.ToUpper(base), + "quote": strings.ToUpper(quote), + } + q := generateQuery(wheres, startDate, endDate) + query := modelPSQL.Trades(q...) + var result []*modelPSQL.Trade + result, err = query.All(context.Background(), database.DB.SQL) + if err != nil { + return td, err + } + for i := range result { + t := Data{ + ID: result[i].ID, + Timestamp: result[i].Timestamp, + Exchange: strings.ToLower(exchangeName), + Base: strings.ToUpper(result[i].Base), + Quote: strings.ToUpper(result[i].Quote), + AssetType: strings.ToLower(result[i].Asset), + Price: result[i].Price, + Amount: result[i].Amount, + } + if result[i].Side.Valid { + t.Side = result[i].Side.String + } + td = append(td, t) + } + return td, nil +} + +// DeleteTrades will remove trades from the database using trade.Data +func DeleteTrades(trades ...Data) error { + ctx := context.Background() + ctx = boil.SkipTimestamps(ctx) + + tx, err := database.DB.SQL.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("beginTx %w", err) + } + defer func() { + if err != nil { + errRB := tx.Rollback() + if errRB != nil { + log.Errorf(log.DatabaseMgr, "DeleteTrades tx.Rollback %v", errRB) + } + } + }() + if repository.GetSQLDialect() == database.DBSQLite3 || repository.GetSQLDialect() == database.DBSQLite { + err = deleteTradesSQLite(context.Background(), tx, trades...) + } else { + err = deleteTradesPostgres(context.Background(), tx, trades...) + } + if err != nil { + return err + } + + return tx.Commit() +} + +func deleteTradesSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error { + var tradeIDs []interface{} + for i := range trades { + tradeIDs = append(tradeIDs, trades[i].ID) + } + query := modelSQLite.Trades(qm.WhereIn(`id in ?`, tradeIDs...)) + _, err := query.DeleteAll(ctx, tx) + return err +} + +func deleteTradesPostgres(ctx context.Context, tx *sql.Tx, trades ...Data) error { + var tradeIDs []interface{} + for i := range trades { + tradeIDs = append(tradeIDs, trades[i].ID) + } + query := modelPSQL.Trades(qm.WhereIn(`id in ?`, tradeIDs...)) + _, err := query.DeleteAll(ctx, tx) + return err +} + +func generateQuery(clauses map[string]interface{}, start, end time.Time) []qm.QueryMod { + query := []qm.QueryMod{ + qm.Where("timestamp BETWEEN ? AND ?", start.UTC().Format(time.RFC3339), end.UTC().Format(time.RFC3339)), + } + for k, v := range clauses { + query = append(query, qm.Where(k+` = ?`, v)) + } + return query +} diff --git a/database/repository/trade/trade_test.go b/database/repository/trade/trade_test.go new file mode 100644 index 00000000..2bb28423 --- /dev/null +++ b/database/repository/trade/trade_test.go @@ -0,0 +1,201 @@ +package trade + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "testing" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/database" + "github.com/thrasher-corp/gocryptotrader/database/drivers" + "github.com/thrasher-corp/gocryptotrader/database/repository/exchange" + "github.com/thrasher-corp/gocryptotrader/database/testhelpers" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" +) + +var ( + verbose = false + testExchanges = []exchange.Details{ + { + Name: "one", + }, + { + Name: "two", + }, + } +) + +func TestMain(m *testing.M) { + if verbose { + testhelpers.EnableVerboseTestOutput() + } + var err error + testhelpers.PostgresTestDatabase = testhelpers.GetConnectionDetails() + testhelpers.TempDir, err = ioutil.TempDir("", "gct-temp") + if err != nil { + log.Fatal(err) + } + os.Exit(m.Run()) +} + +func TestTrades(t *testing.T) { + testCases := []struct { + name string + config *database.Config + seedDB func() error + runner func(t *testing.T) + closer func(dbConn *database.Instance) error + }{ + { + name: "postgresql", + config: testhelpers.PostgresTestDatabase, + seedDB: seedDB, + }, + { + name: "SQLite", + config: &database.Config{ + Driver: database.DBSQLite3, + ConnectionDetails: drivers.ConnectionDetails{Database: "./testdb"}, + }, + seedDB: seedDB, + }, + } + + for x := range testCases { + test := testCases[x] + + t.Run(test.name, func(t *testing.T) { + if !testhelpers.CheckValidConfig(&test.config.ConnectionDetails) { + t.Skip("database not configured skipping test") + } + + dbConn, err := testhelpers.ConnectToDatabase(test.config) + if err != nil { + t.Fatal(err) + } + + if test.seedDB != nil { + err = test.seedDB() + if err != nil { + t.Error(err) + } + } + + tradeSQLTester(t) + err = testhelpers.CloseDatabase(dbConn) + if err != nil { + t.Error(err) + } + }) + } +} + +func tradeSQLTester(t *testing.T) { + var trades, trades2 []Data + + for i := 0; i < 20; i++ { + uu, _ := uuid.NewV4() + trades = append(trades, Data{ + ID: uu.String(), + Timestamp: time.Now(), + Exchange: testExchanges[0].Name, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + AssetType: asset.Spot.String(), + Price: float64(i * (i + 3)), + Amount: float64(i * (i + 2)), + Side: order.Buy.String(), + TID: fmt.Sprintf("%v", i), + }) + } + err := Insert(trades...) + if err != nil { + t.Fatal(err) + } + // insert the same trades to test conflict resolution + for i := 0; i < 20; i++ { + uu, _ := uuid.NewV4() + trades2 = append(trades2, Data{ + ID: uu.String(), + Timestamp: time.Now(), + Exchange: testExchanges[0].Name, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + AssetType: asset.Spot.String(), + Price: float64(i * (i + 3)), + Amount: float64(i * (i + 2)), + Side: order.Buy.String(), + TID: fmt.Sprintf("%v", i), + }) + } + err = Insert(trades2...) + if err != nil { + t.Fatal(err) + } + resp, err := GetInRange( + testExchanges[0].Name, + asset.Spot.String(), + currency.BTC.String(), + currency.USD.String(), + time.Now().Add(-time.Hour), + time.Now().Add(time.Hour), + ) + if err != nil { + t.Error(err) + } + if len(resp) != 20 { + t.Fatalf("unique constraints failing, got %v", resp) + } + + v, err := GetInRange( + testExchanges[0].Name, + asset.Spot.String(), + currency.BTC.String(), + currency.USD.String(), + time.Now().Add(-time.Hour), + time.Now().Add(time.Hour)) + if err != nil { + t.Error(err) + } + if len(v) == 0 { + t.Error("Bad get!") + } + + err = DeleteTrades(trades...) + if err != nil { + t.Error(err) + } + + err = DeleteTrades(trades2...) + if err != nil { + t.Error(err) + } + + v, err = GetInRange( + testExchanges[0].Name, + asset.Spot.String(), + currency.BTC.String(), + currency.USD.String(), + time.Now().Add(-time.Hour), + time.Now().Add(time.Hour)) + if err != nil { + t.Error(err) + } + if len(v) != 0 { + t.Errorf("should all be ded %v", v) + } +} + +func seedDB() error { + err := exchange.InsertMany(testExchanges) + if err != nil { + return err + } + + return nil +} diff --git a/database/repository/trade/trade_types.go b/database/repository/trade/trade_types.go new file mode 100644 index 00000000..c8994ca9 --- /dev/null +++ b/database/repository/trade/trade_types.go @@ -0,0 +1,19 @@ +package trade + +import "time" + +// Data defines trade data in its simplest +// db friendly form +type Data struct { + ID string + TID string + Exchange string + ExchangeNameID string + Base string + Quote string + AssetType string + Price float64 + Amount float64 + Side string + Timestamp time.Time +} diff --git a/database/testhelpers/test_helpers.go b/database/testhelpers/test_helpers.go index ea617f3a..ad99c355 100644 --- a/database/testhelpers/test_helpers.go +++ b/database/testhelpers/test_helpers.go @@ -117,7 +117,9 @@ func migrateDB(db *sql.DB) error { // EnableVerboseTestOutput enables debug output for SQL queries func EnableVerboseTestOutput() { c := log.GenDefaultSettings() + log.RWM.Lock() log.GlobalLogConfig = &c + log.RWM.Unlock() log.SetupGlobalLogger() DBLogger := database.Logger{} diff --git a/engine/database.go b/engine/database.go index eba33552..feab856f 100644 --- a/engine/database.go +++ b/engine/database.go @@ -27,7 +27,7 @@ func (a *databaseManager) Started() bool { return atomic.LoadInt32(&a.started) == 1 } -func (a *databaseManager) Start() (err error) { +func (a *databaseManager) Start(bot *Engine) (err error) { if atomic.AddInt32(&a.started, 1) != 1 { return errors.New("database manager already started") } @@ -42,20 +42,20 @@ func (a *databaseManager) Start() (err error) { a.shutdown = make(chan struct{}) - if Bot.Config.Database.Enabled { - if Bot.Config.Database.Driver == database.DBPostgreSQL { + if bot.Config.Database.Enabled { + if bot.Config.Database.Driver == database.DBPostgreSQL { log.Debugf(log.DatabaseMgr, "Attempting to establish database connection to host %s/%s utilising %s driver\n", - Bot.Config.Database.Host, - Bot.Config.Database.Database, - Bot.Config.Database.Driver) + bot.Config.Database.Host, + bot.Config.Database.Database, + bot.Config.Database.Driver) dbConn, err = dbpsql.Connect() - } else if Bot.Config.Database.Driver == database.DBSQLite || - Bot.Config.Database.Driver == database.DBSQLite3 { + } else if bot.Config.Database.Driver == database.DBSQLite || + bot.Config.Database.Driver == database.DBSQLite3 { log.Debugf(log.DatabaseMgr, "Attempting to establish database connection to %s utilising %s driver\n", - Bot.Config.Database.Database, - Bot.Config.Database.Driver) + bot.Config.Database.Database, + bot.Config.Database.Driver) dbConn, err = dbsqlite3.Connect() } if err != nil { @@ -64,12 +64,12 @@ func (a *databaseManager) Start() (err error) { dbConn.Connected = true DBLogger := database.Logger{} - if Bot.Config.Database.Verbose { + if bot.Config.Database.Verbose { boil.DebugMode = true boil.DebugWriter = DBLogger } - go a.run() + go a.run(bot) return nil } @@ -94,9 +94,9 @@ func (a *databaseManager) Stop() error { return nil } -func (a *databaseManager) run() { +func (a *databaseManager) run(bot *Engine) { log.Debugln(log.DatabaseMgr, "Database manager started.") - Bot.ServicesWG.Add(1) + bot.ServicesWG.Add(1) t := time.NewTicker(time.Second * 2) @@ -105,7 +105,7 @@ func (a *databaseManager) run() { atomic.CompareAndSwapInt32(&a.stopped, 1, 0) atomic.CompareAndSwapInt32(&a.started, 1, 0) - Bot.ServicesWG.Done() + bot.ServicesWG.Done() log.Debugln(log.DatabaseMgr, "Database manager shutdown.") }() diff --git a/engine/engine.go b/engine/engine.go index 79498001..8fd78062 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -16,6 +16,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/currency/coinmarketcap" "github.com/thrasher-corp/gocryptotrader/dispatch" "github.com/thrasher-corp/gocryptotrader/exchanges/request" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm" gctlog "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio" @@ -216,6 +217,17 @@ func validateSettings(b *Engine, s *Settings, flagSet map[string]bool) { request.MaxRequestJobs = int32(b.Settings.MaxHTTPRequestJobsLimit) } + b.Settings.TradeBufferProcessingInterval = s.TradeBufferProcessingInterval + if b.Settings.TradeBufferProcessingInterval != trade.DefaultProcessorIntervalTime { + if b.Settings.TradeBufferProcessingInterval >= time.Second { + trade.BufferProcessorIntervalTime = b.Settings.TradeBufferProcessingInterval + } else { + b.Settings.TradeBufferProcessingInterval = trade.DefaultProcessorIntervalTime + gctlog.Warnf(gctlog.Global, "-tradeprocessinginterval must be >= to 1 second, using default value of %v", + trade.DefaultProcessorIntervalTime) + } + } + b.Settings.RequestMaxRetryAttempts = s.RequestMaxRetryAttempts if b.Settings.RequestMaxRetryAttempts != request.DefaultMaxRetryAttempts && s.RequestMaxRetryAttempts > 0 { request.MaxRetryAttempts = b.Settings.RequestMaxRetryAttempts @@ -297,6 +309,7 @@ func PrintSettings(s *Settings) { gctlog.Debugf(gctlog.Global, "\t Enable exchange HTTP debugging: %v", s.EnableExchangeHTTPDebugging) gctlog.Debugf(gctlog.Global, "\t Max HTTP request jobs: %v", s.MaxHTTPRequestJobsLimit) gctlog.Debugf(gctlog.Global, "\t HTTP request max retry attempts: %v", s.RequestMaxRetryAttempts) + gctlog.Debugf(gctlog.Global, "\t Trade buffer processing interval: %v", s.TradeBufferProcessingInterval) gctlog.Debugf(gctlog.Global, "\t HTTP timeout: %v", s.HTTPTimeout) gctlog.Debugf(gctlog.Global, "\t HTTP user agent: %v", s.HTTPUserAgent) gctlog.Debugf(gctlog.Global, "- GCTSCRIPT SETTINGS: ") @@ -319,7 +332,7 @@ func (bot *Engine) Start() error { } if bot.Settings.EnableDatabaseManager { - if err := bot.DatabaseManager.Start(); err != nil { + if err := bot.DatabaseManager.Start(bot); err != nil { gctlog.Errorf(gctlog.Global, "Database manager unable to start: %v", err) } } diff --git a/engine/engine_types.go b/engine/engine_types.go index bd752595..71416603 100644 --- a/engine/engine_types.go +++ b/engine/engine_types.go @@ -59,6 +59,7 @@ type Settings struct { EnableExchangeRESTSupport bool EnableExchangeWebsocketSupport bool MaxHTTPRequestJobsLimit int + TradeBufferProcessingInterval time.Duration RequestMaxRetryAttempts int // Global HTTP related settings diff --git a/engine/events_test.go b/engine/events_test.go index 5846d3ca..9784c1d0 100644 --- a/engine/events_test.go +++ b/engine/events_test.go @@ -124,7 +124,6 @@ func TestProcessTicker(t *testing.T) { if Bot == nil { Bot = new(Engine) } - Bot.Settings.Verbose = true e := Event{ Exchange: testExchange, @@ -191,7 +190,6 @@ func TestProcessOrderbook(t *testing.T) { if Bot == nil { Bot = new(Engine) } - Bot.Settings.Verbose = true e := Event{ Exchange: testExchange, @@ -226,7 +224,6 @@ func TestCheckEventCondition(t *testing.T) { if Bot == nil { Bot = new(Engine) } - Bot.Settings.Verbose = true e := Event{ Item: ItemPrice, diff --git a/engine/exchange.go b/engine/exchange.go index 6be8ec14..f962ae2b 100644 --- a/engine/exchange.go +++ b/engine/exchange.go @@ -52,17 +52,17 @@ type exchangeManager struct { exchanges map[string]exchange.IBotExchange } -func dryrunParamInteraction(param string) { - if !Bot.Settings.CheckParamInteraction { +func (bot *Engine) dryrunParamInteraction(param string) { + if !bot.Settings.CheckParamInteraction { return } - if !Bot.Settings.EnableDryRun { + if !bot.Settings.EnableDryRun { log.Warnf(log.Global, "Command line argument '-%s' induces dry run mode."+ " Set -dryrun=false if you wish to override this.", param) - Bot.Settings.EnableDryRun = true + bot.Settings.EnableDryRun = true } } @@ -235,7 +235,7 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err if bot.Settings.EnableAllPairs { if exchCfg.CurrencyPairs != nil { - dryrunParamInteraction("enableallpairs") + bot.dryrunParamInteraction("enableallpairs") assets := exchCfg.CurrencyPairs.GetAssetTypes() for x := range assets { var pairs currency.Pairs @@ -249,12 +249,12 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err } if bot.Settings.EnableExchangeVerbose { - dryrunParamInteraction("exchangeverbose") + bot.dryrunParamInteraction("exchangeverbose") exchCfg.Verbose = true } if bot.Settings.EnableExchangeWebsocketSupport { - dryrunParamInteraction("exchangewebsocketsupport") + bot.dryrunParamInteraction("exchangewebsocketsupport") if exchCfg.Features != nil { if exchCfg.Features.Supports.Websocket { exchCfg.Features.Enabled.Websocket = true @@ -263,7 +263,7 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err } if bot.Settings.EnableExchangeAutoPairUpdates { - dryrunParamInteraction("exchangeautopairupdates") + bot.dryrunParamInteraction("exchangeautopairupdates") if exchCfg.Features != nil { if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates { exchCfg.Features.Enabled.AutoPairUpdates = true @@ -272,7 +272,7 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err } if bot.Settings.DisableExchangeAutoPairUpdates { - dryrunParamInteraction("exchangedisableautopairupdates") + bot.dryrunParamInteraction("exchangedisableautopairupdates") if exchCfg.Features != nil { if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates { exchCfg.Features.Enabled.AutoPairUpdates = false @@ -281,27 +281,27 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err } if bot.Settings.HTTPUserAgent != "" { - dryrunParamInteraction("httpuseragent") + bot.dryrunParamInteraction("httpuseragent") exchCfg.HTTPUserAgent = bot.Settings.HTTPUserAgent } if bot.Settings.HTTPProxy != "" { - dryrunParamInteraction("httpproxy") + bot.dryrunParamInteraction("httpproxy") exchCfg.ProxyAddress = bot.Settings.HTTPProxy } if bot.Settings.HTTPTimeout != exchange.DefaultHTTPTimeout { - dryrunParamInteraction("httptimeout") + bot.dryrunParamInteraction("httptimeout") exchCfg.HTTPTimeout = bot.Settings.HTTPTimeout } if bot.Settings.EnableExchangeHTTPDebugging { - dryrunParamInteraction("exchangehttpdebugging") + bot.dryrunParamInteraction("exchangehttpdebugging") exchCfg.HTTPDebugging = bot.Settings.EnableExchangeHTTPDebugging } if bot.Settings.EnableAllExchanges { - dryrunParamInteraction("enableallexchanges") + bot.dryrunParamInteraction("enableallexchanges") } if !bot.Settings.EnableExchangeHTTPRateLimiter { diff --git a/engine/fake_exchange_test.go b/engine/fake_exchange_test.go index 74294268..3fbd2208 100644 --- a/engine/fake_exchange_test.go +++ b/engine/fake_exchange_test.go @@ -14,6 +14,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -107,7 +108,10 @@ func (h *FakePassingExchange) SetPairs(_ currency.Pairs, _ asset.Item, _ bool) e return nil } func (h *FakePassingExchange) GetAssetTypes() asset.Items { return asset.Items{asset.Spot} } -func (h *FakePassingExchange) GetExchangeHistory(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]exchange.TradeHistory, error) { +func (h *FakePassingExchange) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, nil +} +func (h *FakePassingExchange) GetRecentTrades(_ currency.Pair, _ asset.Item) ([]trade.Data, error) { return nil, nil } func (h *FakePassingExchange) SupportsAutoPairUpdates() bool { return true } diff --git a/engine/helpers.go b/engine/helpers.go index 3fd5c11d..32a90d54 100644 --- a/engine/helpers.go +++ b/engine/helpers.go @@ -116,7 +116,7 @@ func (bot *Engine) SetSubsystem(subsys string, enable bool) error { return bot.NTPManager.Stop() case "database": if enable { - return bot.DatabaseManager.Start() + return bot.DatabaseManager.Start(bot) } return bot.DatabaseManager.Stop() case "exchange_syncer": diff --git a/engine/routines.go b/engine/routines.go index 4fdcc2ac..49776667 100644 --- a/engine/routines.go +++ b/engine/routines.go @@ -288,14 +288,6 @@ func WebsocketDataHandler(exchName string, data interface{}) error { log.Info(log.WebsocketMgr, d) case error: return fmt.Errorf("routines.go exchange %s websocket error - %s", exchName, data) - case stream.TradeData: - if Bot.Settings.Verbose { - log.Infof(log.WebsocketMgr, "%s websocket %s %s trade updated %+v", - exchName, - FormatCurrency(d.CurrencyPair), - d.AssetType, - d) - } case stream.FundingData: if Bot.Settings.Verbose { log.Infof(log.WebsocketMgr, "%s websocket %s %s funding updated %+v", diff --git a/engine/routines_test.go b/engine/routines_test.go index b54d1645..ee515bf7 100644 --- a/engine/routines_test.go +++ b/engine/routines_test.go @@ -33,10 +33,6 @@ func TestHandleData(t *testing.T) { if err == nil { t.Error("Expected nil data error") } - err = WebsocketDataHandler(exchName, stream.TradeData{}) - if err != nil { - t.Error(err) - } err = WebsocketDataHandler(exchName, stream.FundingData{}) if err != nil { t.Error(err) diff --git a/engine/rpcserver.go b/engine/rpcserver.go index daec8a8d..fdebb20b 100644 --- a/engine/rpcserver.go +++ b/engine/rpcserver.go @@ -22,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/common/file" "github.com/thrasher-corp/gocryptotrader/common/file/archive" + "github.com/thrasher-corp/gocryptotrader/common/timeperiods" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/database" "github.com/thrasher-corp/gocryptotrader/database/models/postgres" @@ -34,6 +35,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/gctrpc" "github.com/thrasher-corp/gocryptotrader/gctrpc/auth" gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm" @@ -48,15 +50,18 @@ import ( ) const ( - errExchangeNameUnset = "exchange name unset" - errCurrencyPairUnset = "currency pair unset" - errAssetTypeUnset = "asset type unset" - errDispatchSystem = "dispatch system offline" + errExchangeNameUnset = "exchange name unset" + errCurrencyPairUnset = "currency pair unset" + errStartEndTimesUnset = "invalid start and end times" + errAssetTypeUnset = "asset type unset" + errDispatchSystem = "dispatch system offline" + invalidArguments = "invalid arguments received" ) var ( errExchangeNotLoaded = errors.New("exchange is not loaded/doesn't exist") errExchangeBaseNotFound = errors.New("cannot get exchange base") + errInvalidArguments = errors.New(invalidArguments) ) // RPCServer struct @@ -1246,13 +1251,13 @@ func (s *RPCServer) WithdrawalEventsByDate(_ context.Context, r *gctrpc.Withdraw if err != nil { return nil, err } - - UTCSEndTime, err := time.Parse(common.SimpleTimeFormat, r.End) + var UTCEndTime time.Time + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) if err != nil { return nil, err } - - ret, err := WithdrawEventByDate(r.Exchange, UTCStartTime, UTCSEndTime, int(r.Limit)) + var ret []*withdraw.Response + ret, err = WithdrawEventByDate(r.Exchange, UTCStartTime, UTCEndTime, int(r.Limit)) if err != nil { return nil, err } @@ -1295,7 +1300,6 @@ func (s *RPCServer) GetExchangePairs(_ context.Context, r *gctrpc.GetExchangePai if err != nil { return nil, err } - assetTypes := exchCfg.CurrencyPairs.GetAssetTypes() var a asset.Item @@ -1635,14 +1639,11 @@ func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequ return nil, err } - UTCSEndTime, err := time.Parse(common.SimpleTimeFormat, r.EndDate) + UTCEndTime, err := time.Parse(common.SimpleTimeFormat, r.EndDate) if err != nil { return nil, err } - - loc := time.FixedZone("", int(r.Offset)) - - events, err := audit.GetEvent(UTCStartTime, UTCSEndTime, r.OrderBy, int(r.Limit)) + events, err := audit.GetEvent(UTCStartTime, UTCEndTime, r.OrderBy, int(r.Limit)) if err != nil { return nil, err } @@ -1656,7 +1657,7 @@ func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequ Type: v[x].Type, Identifier: v[x].Identifier, Message: v[x].Message, - Timestamp: v[x].CreatedAt.In(loc).Format(common.SimpleTimeFormat), + Timestamp: v[x].CreatedAt.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), } resp.Events = append(resp.Events, tempEvent) @@ -1677,79 +1678,103 @@ func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequ } // GetHistoricCandles returns historical candles for a given exchange -func (s *RPCServer) GetHistoricCandles(_ context.Context, req *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) { - if req.Exchange == "" { +func (s *RPCServer) GetHistoricCandles(_ context.Context, r *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) { + if r.Exchange == "" { return nil, errors.New(errExchangeNameUnset) } - - if req.Pair.String() == "" { + if r.Pair.String() == "" { return nil, errors.New(errCurrencyPairUnset) } - - var candles kline.Item - var err error - resp := gctrpc.GetHistoricCandlesResponse{ - Interval: kline.Interval(req.TimeInterval).Short(), - Pair: req.Pair, - Start: req.Start, - End: req.End, + if r.Start == r.End { + return nil, errors.New(errStartEndTimesUnset) } - a, err := asset.New(req.AssetType) + var klineItem kline.Item + UTCStartTime, err := time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return nil, err + } + var UTCEndTime time.Time + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return nil, err + } + interval := kline.Interval(r.TimeInterval) + + resp := gctrpc.GetHistoricCandlesResponse{ + Interval: interval.Short(), + Pair: r.Pair, + Start: r.Start, + End: r.End, + } + + a, err := asset.New(r.AssetType) if err != nil { return nil, err } pair := currency.Pair{ - Delimiter: req.Pair.Delimiter, - Base: currency.NewCode(req.Pair.Base), - Quote: currency.NewCode(req.Pair.Quote), + Delimiter: r.Pair.Delimiter, + Base: currency.NewCode(r.Pair.Base), + Quote: currency.NewCode(r.Pair.Quote), } - - if req.UseDb { - candles, err = kline.LoadFromDatabase(req.Exchange, + if r.UseDb { + klineItem, err = kline.LoadFromDatabase(r.Exchange, pair, a, - kline.Interval(req.TimeInterval), - time.Unix(req.Start, 0), - time.Unix(req.End, 0), - ) - } else { - exchangeEngine := s.GetExchangeByName(req.Exchange) - if exchangeEngine == nil { - return nil, errors.New("Exchange " + req.Exchange + " not found") + interval, + UTCStartTime, + UTCEndTime) + if err != nil { + return nil, err } - if req.ExRequest { - candles, err = exchangeEngine.GetHistoricCandlesExtended(pair, + } else { + exchangeEngine := s.GetExchangeByName(r.Exchange) + if exchangeEngine == nil { + return nil, errors.New("Exchange " + r.Exchange + " not found") + } + if r.ExRequest { + klineItem, err = exchangeEngine.GetHistoricCandlesExtended(pair, a, - time.Unix(req.Start, 0), - time.Unix(req.End, 0), - kline.Interval(req.TimeInterval)) + UTCStartTime, + UTCEndTime, + interval) } else { - candles, err = exchangeEngine.GetHistoricCandles(pair, + klineItem, err = exchangeEngine.GetHistoricCandles(pair, a, - time.Unix(req.Start, 0), - time.Unix(req.End, 0), - kline.Interval(req.TimeInterval)) + UTCStartTime, + UTCEndTime, + interval) } } + if err != nil { return nil, err } - resp.Exchange = candles.Exchange - for i := range candles.Candles { + + if r.FillMissingWithTrades { + var tradeDataKline *kline.Item + tradeDataKline, err = fillMissingCandlesWithStoredTrades(UTCStartTime, UTCEndTime, &klineItem) + if err != nil { + return nil, err + } + klineItem.Candles = append(klineItem.Candles, tradeDataKline.Candles...) + } + + resp.Exchange = klineItem.Exchange + for i := range klineItem.Candles { resp.Candle = append(resp.Candle, &gctrpc.Candle{ - Time: candles.Candles[i].Time.Unix(), - Low: candles.Candles[i].Low, - High: candles.Candles[i].High, - Open: candles.Candles[i].Open, - Close: candles.Candles[i].Close, - Volume: candles.Candles[i].Volume, + Time: klineItem.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + Low: klineItem.Candles[i].Low, + High: klineItem.Candles[i].High, + Open: klineItem.Candles[i].Open, + Close: klineItem.Candles[i].Close, + Volume: klineItem.Candles[i].Volume, }) } - if req.Sync && !req.UseDb { - _, err = kline.StoreInDatabase(&candles) + if r.Sync && !r.UseDb { + _, err = kline.StoreInDatabase(&klineItem, r.Force) if err != nil { if errors.Is(err, exchangeDB.ErrNoExchangeFound) { return nil, errors.New("exchange was not found in database, you can seed existing data or insert a new exchange via the dbseed") @@ -1757,9 +1782,66 @@ func (s *RPCServer) GetHistoricCandles(_ context.Context, req *gctrpc.GetHistori return nil, err } } + return &resp, nil } +func fillMissingCandlesWithStoredTrades(startTime, endTime time.Time, klineItem *kline.Item) (*kline.Item, error) { + var response kline.Item + var candleTimes []time.Time + for i := range klineItem.Candles { + candleTimes = append(candleTimes, klineItem.Candles[i].Time) + } + ranges, err := timeperiods.FindTimeRangesContainingData(startTime, endTime, klineItem.Interval.Duration(), candleTimes) + if err != nil { + return nil, err + } + + for i := range ranges { + if ranges[i].HasDataInRange { + continue + } + var tradeCandles kline.Item + trades, err := trade.GetTradesInRange( + klineItem.Exchange, + klineItem.Asset.String(), + klineItem.Pair.Base.String(), + klineItem.Pair.Quote.String(), + ranges[i].StartOfRange, + ranges[i].EndOfRange, + ) + if err != nil { + return klineItem, err + } + if len(trades) == 0 { + continue + } + tradeCandles, err = trade.ConvertTradesToCandles(klineItem.Interval, trades...) + if err != nil { + return klineItem, err + } + if len(tradeCandles.Candles) == 0 { + continue + } + + for i := range tradeCandles.Candles { + response.Candles = append(response.Candles, tradeCandles.Candles[i]) + } + + for i := range response.Candles { + log.Infof(log.GRPCSys, + "Filled requested OHLCV data for %v %v %v interval at %v with trade data", + klineItem.Exchange, + klineItem.Pair.String(), + klineItem.Asset, + response.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + ) + } + } + + return &response, nil +} + // GCTScriptStatus returns a slice of current running scripts that includes next run time and uuid func (s *RPCServer) GCTScriptStatus(_ context.Context, r *gctrpc.GCTScriptStatusRequest) (*gctrpc.GCTScriptStatusResponse, error) { if !gctscript.GCTScriptConfig.Enabled { @@ -2313,3 +2395,485 @@ func (s *RPCServer) WebsocketSetURL(_ context.Context, r *gctrpc.WebsocketSetURL r.Exchange, r.Url)}, nil } + +// GetSavedTrades returns trades from the database +func (s *RPCServer) GetSavedTrades(_ context.Context, r *gctrpc.GetSavedTradesRequest) (*gctrpc.SavedTradesResponse, error) { + if r.End == "" || r.Start == "" || r.Exchange == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" { + return nil, errInvalidArguments + } + exch := s.GetExchangeByName(r.Exchange) + if exch == nil { + return nil, errExchangeNotLoaded + } + + cp, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return nil, err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return nil, errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return nil, err + } + if !pairs.Contains(cp, false) { + return nil, errors.New("currency not enabled") + } + + var UTCStartTime, UTCEndTime time.Time + UTCStartTime, err = time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return nil, err + } + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return nil, err + } + var trades []trade.Data + trades, err = trade.GetTradesInRange(r.Exchange, r.AssetType, r.Pair.Base, r.Pair.Quote, UTCStartTime, UTCEndTime) + if err != nil { + return nil, err + } + resp := &gctrpc.SavedTradesResponse{ + ExchangeName: r.Exchange, + Asset: r.AssetType, + Pair: r.Pair, + } + for i := range trades { + resp.Trades = append(resp.Trades, &gctrpc.SavedTrades{ + Price: trades[i].Price, + Amount: trades[i].Amount, + Side: trades[i].Side.String(), + Timestamp: trades[i].Timestamp.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + TradeId: trades[i].TID, + }) + } + if len(resp.Trades) == 0 { + return nil, fmt.Errorf("request for %v %v trade data between %v and %v and returned no results", r.Exchange, r.AssetType, r.Start, r.End) + } + return resp, nil +} + +// ConvertTradesToCandles converts trades to candles using the interval requested +// returns the data too for extra fun scrutiny +func (s *RPCServer) ConvertTradesToCandles(_ context.Context, r *gctrpc.ConvertTradesToCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) { + if r.End == "" || r.Start == "" || r.Exchange == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" || r.TimeInterval == 0 { + return nil, errInvalidArguments + } + exch := s.GetExchangeByName(r.Exchange) + UTCStartTime, err := time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return nil, err + } + var UTCEndTime time.Time + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return nil, err + } + if exch == nil { + return nil, errExchangeNotLoaded + } + var cp currency.Pair + cp, err = currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return nil, err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return nil, errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return nil, err + } + if !pairs.Contains(cp, false) { + return nil, errors.New("currency not enabled") + } + + var trades []trade.Data + trades, err = trade.GetTradesInRange(r.Exchange, r.AssetType, r.Pair.Base, r.Pair.Quote, UTCStartTime, UTCEndTime) + if err != nil { + return nil, err + } + if len(trades) == 0 { + return nil, fmt.Errorf("no trades returned from supplied params") + } + interval := kline.Interval(r.TimeInterval) + var klineItem kline.Item + klineItem, err = trade.ConvertTradesToCandles(interval, trades...) + if err != nil { + return nil, err + } + if len(klineItem.Candles) == 0 { + return nil, fmt.Errorf("no candles generated from trades") + } + + resp := &gctrpc.GetHistoricCandlesResponse{ + Exchange: r.Exchange, + Pair: r.Pair, + Start: r.Start, + End: r.End, + Interval: interval.String(), + } + for i := range klineItem.Candles { + resp.Candle = append(resp.Candle, &gctrpc.Candle{ + Time: klineItem.Candles[i].Time.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + Low: klineItem.Candles[i].Low, + High: klineItem.Candles[i].High, + Open: klineItem.Candles[i].Open, + Close: klineItem.Candles[i].Close, + Volume: klineItem.Candles[i].Volume, + }) + } + + if r.Sync { + _, err = kline.StoreInDatabase(&klineItem, r.Force) + if err != nil { + return nil, err + } + } + + return resp, nil +} + +// FindMissingSavedCandleIntervals is used to help determine what candle data is missing +func (s *RPCServer) FindMissingSavedCandleIntervals(_ context.Context, r *gctrpc.FindMissingCandlePeriodsRequest) (*gctrpc.FindMissingIntervalsResponse, error) { + if r.End == "" || r.Start == "" || r.ExchangeName == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" || r.Interval <= 0 { + return nil, errInvalidArguments + } + exch := s.GetExchangeByName(r.ExchangeName) + if exch == nil { + return nil, errExchangeNotLoaded + } + + cp, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return nil, err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return nil, errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return nil, err + } + if !pairs.Contains(cp, false) { + return nil, errors.New("currency not enabled") + } + + var UTCStartTime, UTCEndTime time.Time + UTCStartTime, err = time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return nil, err + } + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return nil, err + } + klineItem, err := kline.LoadFromDatabase( + r.ExchangeName, + currency.Pair{ + Delimiter: r.Pair.Delimiter, + Base: currency.NewCode(r.Pair.Base), + Quote: currency.NewCode(r.Pair.Quote), + }, + asset.Item(strings.ToLower(r.AssetType)), + kline.Interval(r.Interval), + UTCStartTime, + UTCEndTime, + ) + if err != nil { + return nil, err + } + resp := &gctrpc.FindMissingIntervalsResponse{ + ExchangeName: r.ExchangeName, + AssetType: r.AssetType, + Pair: r.Pair, + MissingPeriods: []string{}, + } + var candleTimes []time.Time + for i := range klineItem.Candles { + candleTimes = append(candleTimes, klineItem.Candles[i].Time) + } + var ranges []timeperiods.TimeRange + ranges, err = timeperiods.FindTimeRangesContainingData(UTCStartTime, UTCEndTime, klineItem.Interval.Duration(), candleTimes) + if err != nil { + return nil, err + } + foundCount := 0 + for i := range ranges { + if !ranges[i].HasDataInRange { + resp.MissingPeriods = append(resp.MissingPeriods, + ranges[i].StartOfRange.UTC().Format(common.SimpleTimeFormatWithTimezone)+ + " - "+ + ranges[i].EndOfRange.UTC().Format(common.SimpleTimeFormatWithTimezone)) + } else { + foundCount++ + } + } + + if len(resp.MissingPeriods) == 0 { + resp.Status = fmt.Sprintf("no missing candles found between %v and %v", + r.Start, + r.End, + ) + } else { + resp.Status = fmt.Sprintf("Found %v candles. Missing %v candles in requested timeframe starting %v ending %v", + foundCount, + len(resp.MissingPeriods), + UTCStartTime.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + UTCEndTime.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone)) + } + + return resp, nil +} + +// FindMissingSavedTradeIntervals is used to help determine what trade data is missing +func (s *RPCServer) FindMissingSavedTradeIntervals(_ context.Context, r *gctrpc.FindMissingTradePeriodsRequest) (*gctrpc.FindMissingIntervalsResponse, error) { + if r.End == "" || r.Start == "" || r.ExchangeName == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" { + return nil, errInvalidArguments + } + exch := s.GetExchangeByName(r.ExchangeName) + if exch == nil { + return nil, errExchangeNotLoaded + } + var err error + var UTCStartTime, UTCEndTime time.Time + UTCStartTime, err = time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return nil, err + } + UTCStartTime = UTCStartTime.Truncate(time.Hour) + + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return nil, err + } + UTCEndTime = UTCEndTime.Truncate(time.Hour) + + intervalMap := make(map[time.Time]bool) + iterationTime := UTCStartTime + for iterationTime.Before(UTCEndTime) { + intervalMap[iterationTime] = false + iterationTime = iterationTime.Add(time.Hour) + } + var cp currency.Pair + cp, err = currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return nil, err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return nil, errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return nil, err + } + if !pairs.Contains(cp, false) { + return nil, errors.New("currency not enabled") + } + + var trades []trade.Data + trades, err = trade.GetTradesInRange( + r.ExchangeName, + r.AssetType, + r.Pair.Base, + r.Pair.Quote, + UTCStartTime, + UTCEndTime, + ) + if err != nil { + return nil, err + } + resp := &gctrpc.FindMissingIntervalsResponse{ + ExchangeName: r.ExchangeName, + AssetType: r.AssetType, + Pair: r.Pair, + MissingPeriods: []string{}, + } + var tradeTimes []time.Time + for i := range trades { + tradeTimes = append(tradeTimes, trades[i].Timestamp) + } + var ranges []timeperiods.TimeRange + ranges, err = timeperiods.FindTimeRangesContainingData(UTCStartTime, UTCEndTime, time.Hour, tradeTimes) + if err != nil { + return nil, err + } + foundCount := 0 + for i := range ranges { + if !ranges[i].HasDataInRange { + resp.MissingPeriods = append(resp.MissingPeriods, + ranges[i].StartOfRange.UTC().Format(common.SimpleTimeFormatWithTimezone)+ + " - "+ + ranges[i].EndOfRange.UTC().Format(common.SimpleTimeFormatWithTimezone)) + } else { + foundCount++ + } + } + + if len(resp.MissingPeriods) == 0 { + resp.Status = fmt.Sprintf("no missing periods found between %v and %v", + r.Start, + r.End, + ) + } else { + resp.Status = fmt.Sprintf("Found %v periods. Missing %v periods between %v and %v", + foundCount, + len(resp.MissingPeriods), + UTCStartTime.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + UTCEndTime.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone)) + } + + return resp, nil +} + +// SetExchangeTradeProcessing allows the setting of exchange trade processing +func (s *RPCServer) SetExchangeTradeProcessing(_ context.Context, r *gctrpc.SetExchangeTradeProcessingRequest) (*gctrpc.GenericResponse, error) { + exch := s.GetExchangeByName(r.Exchange) + if exch == nil { + return nil, errExchangeNotLoaded + } + b := exch.GetBase() + b.SetSaveTradeDataStatus(r.Status) + + return &gctrpc.GenericResponse{ + Status: "success", + }, nil +} + +// GetHistoricTrades returns trades between a set of dates +func (s *RPCServer) GetHistoricTrades(r *gctrpc.GetSavedTradesRequest, stream gctrpc.GoCryptoTrader_GetHistoricTradesServer) error { + if r.Exchange == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" { + return errInvalidArguments + } + exch := s.GetExchangeByName(r.Exchange) + if exch == nil { + return errExchangeNotLoaded + } + cp, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return err + } + if !pairs.Contains(cp, false) { + return errors.New("currency not enabled") + } + var trades []trade.Data + var UTCStartTime, UTCEndTime time.Time + UTCStartTime, err = time.Parse(common.SimpleTimeFormat, r.Start) + if err != nil { + return err + } + + UTCEndTime, err = time.Parse(common.SimpleTimeFormat, r.End) + if err != nil { + return err + } + + resp := &gctrpc.SavedTradesResponse{ + ExchangeName: r.Exchange, + Asset: r.AssetType, + Pair: r.Pair, + } + iterateStartTime := UTCStartTime + iterateEndTime := iterateStartTime.Add(time.Hour) + for iterateStartTime.Before(UTCEndTime) { + trades, err = exch.GetHistoricTrades(cp, asset.Item(r.AssetType), iterateStartTime, iterateEndTime) + if err != nil { + return err + } + grpcTrades := &gctrpc.SavedTradesResponse{ + ExchangeName: r.Exchange, + Asset: r.AssetType, + Pair: r.Pair, + } + for i := range trades { + tradeTS := trades[i].Timestamp.In(time.UTC) + if tradeTS.After(UTCEndTime) { + break + } + grpcTrades.Trades = append(grpcTrades.Trades, &gctrpc.SavedTrades{ + Price: trades[i].Price, + Amount: trades[i].Amount, + Side: trades[i].Side.String(), + Timestamp: tradeTS.Format(common.SimpleTimeFormatWithTimezone), + TradeId: trades[i].TID, + }) + } + + stream.Send(grpcTrades) + iterateStartTime = iterateStartTime.Add(time.Hour) + iterateEndTime = iterateEndTime.Add(time.Hour) + } + stream.Send(resp) + + return nil +} + +// GetRecentTrades returns trades +func (s *RPCServer) GetRecentTrades(_ context.Context, r *gctrpc.GetSavedTradesRequest) (*gctrpc.SavedTradesResponse, error) { + if r.Exchange == "" || r.Pair == nil || r.AssetType == "" || r.Pair.String() == "" { + return nil, errInvalidArguments + } + exch := s.GetExchangeByName(r.Exchange) + if exch == nil { + return nil, errExchangeNotLoaded + } + cp, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote) + if err != nil { + return nil, err + } + a := asset.Item(r.AssetType) + if !a.IsValid() { + return nil, errors.New("invalid asset") + } + var pairs currency.Pairs + pairs, err = exch.GetEnabledPairs(a) + if err != nil { + return nil, err + } + if !pairs.Contains(cp, false) { + return nil, errors.New("currency not enabled") + } + var trades []trade.Data + trades, err = exch.GetRecentTrades(cp, asset.Item(r.AssetType)) + if err != nil { + return nil, err + } + resp := &gctrpc.SavedTradesResponse{ + ExchangeName: r.Exchange, + Asset: r.AssetType, + Pair: r.Pair, + } + for i := range trades { + resp.Trades = append(resp.Trades, &gctrpc.SavedTrades{ + Price: trades[i].Price, + Amount: trades[i].Amount, + Side: trades[i].Side.String(), + Timestamp: trades[i].Timestamp.In(time.UTC).Format(common.SimpleTimeFormatWithTimezone), + TradeId: trades[i].TID, + }) + } + if len(resp.Trades) == 0 { + return nil, fmt.Errorf("request for %v %v trade data and returned no results", r.Exchange, r.AssetType) + } + + return resp, nil +} diff --git a/engine/rpcserver_test.go b/engine/rpcserver_test.go new file mode 100644 index 00000000..83b6adb8 --- /dev/null +++ b/engine/rpcserver_test.go @@ -0,0 +1,787 @@ +package engine + +import ( + "context" + "errors" + "log" + "os" + "path/filepath" + "runtime" + "testing" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/config" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/database" + "github.com/thrasher-corp/gocryptotrader/database/drivers" + "github.com/thrasher-corp/gocryptotrader/database/repository" + "github.com/thrasher-corp/gocryptotrader/database/repository/exchange" + sqltrade "github.com/thrasher-corp/gocryptotrader/database/repository/trade" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" + "github.com/thrasher-corp/gocryptotrader/gctrpc" + "github.com/thrasher-corp/goose" +) + +const ( + unexpectedLackOfError = "unexpected lack of error" + migrationsFolder = "migrations" + databaseFolder = "database" + databaseName = "rpctestdb" +) + +// Sets up everything required to run any function inside rpcserver +func RPCTestSetup(t *testing.T) *Engine { + database.DB.Mu.Lock() + var err error + dbConf := database.Config{ + Enabled: true, + Driver: database.DBSQLite3, + ConnectionDetails: drivers.ConnectionDetails{ + Database: databaseName, + }, + } + engerino := new(Engine) + engerino.Config = &config.Config{} + err = engerino.Config.LoadConfig(config.TestFile, true) + if err != nil { + t.Fatalf("SetupTest: Failed to load config: %s", err) + } + + if engerino.GetExchangeByName(testExchange) == nil { + err = engerino.LoadExchange(testExchange, false, nil) + if err != nil { + t.Fatalf("SetupTest: Failed to load exchange: %s", err) + } + } + engerino.Config.Database = dbConf + err = engerino.DatabaseManager.Start(engerino) + if err != nil { + log.Fatal(err) + } + path := filepath.Join("..", databaseFolder, migrationsFolder) + err = goose.Run("up", dbConn.SQL, repository.GetSQLDialect(), path, "") + if err != nil { + t.Fatalf("failed to run migrations %v", err) + } + uuider, _ := uuid.NewV4() + err = exchange.Insert(exchange.Details{Name: testExchange, UUID: uuider}) + if err != nil { + t.Fatalf("failed to insert exchange %v", err) + } + database.DB.Mu.Unlock() + + return engerino +} + +func CleanRPCTest(t *testing.T, engerino *Engine) { + database.DB.Mu.Lock() + defer database.DB.Mu.Unlock() + err := engerino.DatabaseManager.Stop() + if err != nil { + t.Error(err) + return + } + err = os.Remove(filepath.Join(common.GetDefaultDataDir(runtime.GOOS), databaseFolder, databaseName)) + if err != nil { + t.Error(err) + } +} + +func TestGetSavedTrades(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + _, err := s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{}) + if err == nil { + t.Fatal(unexpectedLackOfError) + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + } + _, err = s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{ + Exchange: "fake", + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err != errExchangeNotLoaded { + t.Error(err) + } + _, err = s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err.Error() != "request for Bitstamp spot trade data between 2019-11-30 00:00:00 and 2020-01-01 01:01:01 and returned no results" { + t.Error(err) + } + err = sqltrade.Insert(sqltrade.Data{ + Timestamp: time.Date(2020, 0, 0, 0, 0, 1, 0, time.UTC), + Exchange: testExchange, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + AssetType: asset.Spot.String(), + Price: 1337, + Amount: 1337, + Side: order.Buy.String(), + }) + if err != nil { + t.Error(err) + return + } + _, err = s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } +} + +func TestConvertTradesToCandles(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + // bad param test + _, err := s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{}) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + } + + // bad exchange test + _, err = s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: "faker", + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + }) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err != errExchangeNotLoaded { + t.Error(err) + } + + // no trades test + _, err = s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + }) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err.Error() != "no trades returned from supplied params" { + t.Error(err) + } + + // add a trade + err = sqltrade.Insert(sqltrade.Data{ + Timestamp: time.Date(2020, 1, 1, 1, 1, 2, 1, time.UTC), + Exchange: testExchange, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + AssetType: asset.Spot.String(), + Price: 1337, + Amount: 1337, + Side: order.Buy.String(), + }) + if err != nil { + t.Error(err) + return + } + + // get candle from one trade + var candles *gctrpc.GetHistoricCandlesResponse + candles, err = s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + }) + if err != nil { + t.Error(err) + } + if len(candles.Candle) == 0 { + t.Error("no candles returned") + } + + // save generated candle to database + _, err = s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + Sync: true, + }) + if err != nil { + t.Error(err) + } + + // forcefully remove previous candle and insert a new one + _, err = s.ConvertTradesToCandles(context.Background(), &gctrpc.ConvertTradesToCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + Sync: true, + Force: true, + }) + if err != nil { + t.Error(err) + } + + // load the saved candle to verify that it was overwritten + candles, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 2, 2, 2, 2, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + UseDb: true, + }) + if err != nil { + t.Error(err) + } + + if len(candles.Candle) != 1 { + t.Error("expected only one candle") + } +} + +func TestGetHistoricCandles(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + // error checks + _, err := s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: "", + }) + if err != nil && err.Error() != errExchangeNameUnset { + t.Error(err) + } + + _, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{}, + }) + if err != nil && err.Error() != errCurrencyPairUnset { + t.Error(err) + } + _, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + }) + if err != nil && err.Error() != errStartEndTimesUnset { + t.Error(err) + } + var results *gctrpc.GetHistoricCandlesResponse + defaultStart := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC) + defaultEnd := time.Date(2020, 1, 2, 2, 2, 2, 2, time.UTC) + cp := currency.NewPair(currency.BTC, currency.USD) + // default run + results, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + AssetType: asset.Spot.String(), + TimeInterval: int64(kline.OneHour.Duration()), + }) + if err != nil { + t.Error(err) + } + if len(results.Candle) == 0 { + t.Error("expected results") + } + + // sync run + results, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + AssetType: asset.Spot.String(), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + Sync: true, + ExRequest: true, + }) + if err != nil { + t.Error(err) + } + if len(results.Candle) == 0 { + t.Error("expected results") + } + + // db run + results, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + AssetType: asset.Spot.String(), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + UseDb: true, + }) + if err != nil { + t.Error(err) + } + if len(results.Candle) == 0 { + t.Error("expected results") + } + err = trade.SaveTradesToDatabase(trade.Data{ + TID: "test123", + Exchange: testExchange, + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + Timestamp: time.Date(2020, 1, 2, 3, 1, 1, 7, time.UTC), + }) + if err != nil { + t.Error(err) + return + } + // db run including trades + results, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + AssetType: asset.Spot.String(), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 2, 4, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + TimeInterval: int64(kline.OneHour.Duration()), + UseDb: true, + FillMissingWithTrades: true, + }) + if err != nil { + t.Error(err) + } + if results.Candle[len(results.Candle)-1].Close != 1337 { + t.Error("expected fancy new candle based off fancy new trade data") + } +} + +func TestFindMissingSavedTradeIntervals(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + // bad request checks + _, err := s.FindMissingSavedTradeIntervals(context.Background(), &gctrpc.FindMissingTradePeriodsRequest{}) + if err == nil { + t.Error("expected error") + return + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + return + } + cp := currency.NewPair(currency.BTC, currency.USD) + // no data found response + defaultStart := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC).UTC() + defaultEnd := time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC).UTC() + var resp *gctrpc.FindMissingIntervalsResponse + resp, err = s.FindMissingSavedTradeIntervals(context.Background(), &gctrpc.FindMissingTradePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Start: defaultStart.UTC().Format(common.SimpleTimeFormat), + End: defaultEnd.UTC().Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } + if resp.Status == "" { + t.Errorf("expected a status message") + } + // one trade response + err = trade.SaveTradesToDatabase(trade.Data{ + TID: "test1234", + Exchange: testExchange, + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + Timestamp: time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC), + }) + if err != nil { + t.Error(err) + return + } + + resp, err = s.FindMissingSavedTradeIntervals(context.Background(), &gctrpc.FindMissingTradePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Start: defaultStart.In(time.UTC).Format(common.SimpleTimeFormat), + End: defaultEnd.In(time.UTC).Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } + if len(resp.MissingPeriods) != 2 { + t.Errorf("expected 2 missing period, received: %v", len(resp.MissingPeriods)) + } + + // two trades response + err = trade.SaveTradesToDatabase(trade.Data{ + TID: "test123", + Exchange: testExchange, + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + Timestamp: time.Date(2020, 1, 1, 13, 0, 0, 0, time.UTC), + }) + if err != nil { + t.Error(err) + return + } + + resp, err = s.FindMissingSavedTradeIntervals(context.Background(), &gctrpc.FindMissingTradePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Start: defaultStart.In(time.UTC).Format(common.SimpleTimeFormat), + End: defaultEnd.In(time.UTC).Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } + if len(resp.MissingPeriods) != 2 { + t.Errorf("expected 2 missing periods, received: %v", len(resp.MissingPeriods)) + } +} + +func TestFindMissingSavedCandleIntervals(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + // bad request checks + _, err := s.FindMissingSavedCandleIntervals(context.Background(), &gctrpc.FindMissingCandlePeriodsRequest{}) + if err == nil { + t.Error("expected error") + return + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + return + } + cp := currency.NewPair(currency.BTC, currency.USD) + // no data found response + defaultStart := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC) + defaultEnd := time.Date(2020, 1, 2, 2, 2, 2, 2, time.UTC) + var resp *gctrpc.FindMissingIntervalsResponse + _, err = s.FindMissingSavedCandleIntervals(context.Background(), &gctrpc.FindMissingCandlePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Interval: int64(time.Hour), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + }) + if err != nil && err.Error() != "no candle data found: Bitstamp BTC USD 3600 spot" { + t.Error(err) + return + } + + // one candle missing periods response + _, err = kline.StoreInDatabase(&kline.Item{ + Exchange: testExchange, + Pair: cp, + Asset: asset.Spot, + Interval: kline.OneHour, + Candles: []kline.Candle{ + { + Time: time.Date(2020, 1, 1, 2, 1, 1, 1, time.UTC), + Open: 1337, + High: 1337, + Low: 1337, + Close: 1337, + Volume: 1337, + }, + }, + }, false) + if err != nil { + t.Error(err) + return + } + + _, err = s.FindMissingSavedCandleIntervals(context.Background(), &gctrpc.FindMissingCandlePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Interval: int64(time.Hour), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } + + // two candle missing periods response + _, err = kline.StoreInDatabase(&kline.Item{ + Exchange: testExchange, + Pair: cp, + Asset: asset.Spot, + Interval: kline.OneHour, + Candles: []kline.Candle{ + { + Time: time.Date(2020, 1, 1, 3, 1, 1, 1, time.UTC), + Open: 1337, + High: 1337, + Low: 1337, + Close: 1337, + Volume: 1337, + }, + }, + }, false) + if err != nil { + t.Error(err) + return + } + + resp, err = s.FindMissingSavedCandleIntervals(context.Background(), &gctrpc.FindMissingCandlePeriodsRequest{ + ExchangeName: testExchange, + AssetType: asset.Spot.String(), + Pair: &gctrpc.CurrencyPair{ + Base: cp.Base.String(), + Quote: cp.Quote.String(), + }, + Interval: int64(time.Hour), + Start: defaultStart.Format(common.SimpleTimeFormat), + End: defaultEnd.Format(common.SimpleTimeFormat), + }) + if err != nil { + t.Error(err) + } + if len(resp.MissingPeriods) != 2 { + t.Errorf("expected 2 missing periods, received: %v", len(resp.MissingPeriods)) + } +} + +func TestSetExchangeTradeProcessing(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + _, err := s.SetExchangeTradeProcessing(context.Background(), &gctrpc.SetExchangeTradeProcessingRequest{Exchange: testExchange, Status: true}) + if err != nil { + t.Error(err) + return + } + exch := s.GetExchangeByName(testExchange) + base := exch.GetBase() + if !base.IsSaveTradeDataEnabled() { + t.Error("expected true") + } + + _, err = s.SetExchangeTradeProcessing(context.Background(), &gctrpc.SetExchangeTradeProcessingRequest{Exchange: testExchange, Status: false}) + if err != nil { + t.Error(err) + return + } + exch = s.GetExchangeByName(testExchange) + base = exch.GetBase() + if base.IsSaveTradeDataEnabled() { + t.Error("expected false") + } +} + +func TestGetRecentTrades(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + _, err := s.GetRecentTrades(context.Background(), &gctrpc.GetSavedTradesRequest{}) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + } + _, err = s.GetRecentTrades(context.Background(), &gctrpc.GetSavedTradesRequest{ + Exchange: "fake", + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err != errExchangeNotLoaded { + t.Error(err) + } + _, err = s.GetRecentTrades(context.Background(), &gctrpc.GetSavedTradesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + }) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + engerino := RPCTestSetup(t) + defer CleanRPCTest(t, engerino) + s := RPCServer{engerino} + err := s.GetHistoricTrades(&gctrpc.GetSavedTradesRequest{}, nil) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if !errors.Is(err, errInvalidArguments) { + t.Error(err) + } + err = s.GetHistoricTrades(&gctrpc.GetSavedTradesRequest{ + Exchange: "fake", + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }, nil) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err != errExchangeNotLoaded { + t.Error(err) + } + err = s.GetHistoricTrades(&gctrpc.GetSavedTradesRequest{ + Exchange: testExchange, + Pair: &gctrpc.CurrencyPair{ + Delimiter: currency.DashDelimiter, + Base: currency.BTC.String(), + Quote: currency.USD.String(), + }, + AssetType: asset.Spot.String(), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + }, nil) + if err == nil { + t.Error(unexpectedLackOfError) + return + } + if err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/engine/syncer_test.go b/engine/syncer_test.go index 7a37dcf7..f28e69ea 100644 --- a/engine/syncer_test.go +++ b/engine/syncer_test.go @@ -20,7 +20,6 @@ func TestNewCurrencyPairSyncer(t *testing.T) { } Bot.Settings.DisableExchangeAutoPairUpdates = true - Bot.Settings.Verbose = true Bot.Settings.EnableExchangeWebsocketSupport = true Bot.SetupExchanges() diff --git a/exchanges/alphapoint/alphapoint_test.go b/exchanges/alphapoint/alphapoint_test.go index abc430a7..33abc7aa 100644 --- a/exchanges/alphapoint/alphapoint_test.go +++ b/exchanges/alphapoint/alphapoint_test.go @@ -5,6 +5,7 @@ import ( "log" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/core" @@ -595,3 +596,27 @@ func TestWithdrawInternationalBank(t *testing.T) { t.Errorf("Expected '%v', received: '%v'", common.ErrNotYetImplemented, err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = a.GetRecentTrades(currencyPair, asset.Spot) + if err != nil && err != common.ErrNotYetImplemented { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = a.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrNotYetImplemented { + t.Error(err) + } +} diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go index f0c73f49..3b6c126d 100644 --- a/exchanges/alphapoint/alphapoint_wrapper.go +++ b/exchanges/alphapoint/alphapoint_wrapper.go @@ -16,6 +16,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -206,8 +207,13 @@ func (a *Alphapoint) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrNotYetImplemented } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (a *Alphapoint) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { +// GetRecentTrades returns the most recent trades for a currency and asset +func (a *Alphapoint) GetRecentTrades(_ currency.Pair, _ asset.Item) ([]trade.Data, error) { + return nil, common.ErrNotYetImplemented +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (a *Alphapoint) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { return nil, common.ErrNotYetImplemented } diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index 5f1d22e6..67616faf 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -135,9 +135,9 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error return orderbook, nil } -// GetRecentTrades returns recent trade activity +// GetMostRecentTrades returns recent trade activity // limit: Up to 500 results returned -func (b *Binance) GetRecentTrades(rtr RecentTradeRequestParams) ([]RecentTrade, error) { +func (b *Binance) GetMostRecentTrades(rtr RecentTradeRequestParams) ([]RecentTrade, error) { var resp []RecentTrade params := url.Values{} diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index fd458344..099f3811 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -66,16 +66,16 @@ func TestGetOrderBook(t *testing.T) { } } -func TestGetRecentTrades(t *testing.T) { +func TestGetMostRecentTrades(t *testing.T) { t.Parallel() - _, err := b.GetRecentTrades(RecentTradeRequestParams{ + _, err := b.GetMostRecentTrades(RecentTradeRequestParams{ Symbol: "BTCUSDT", Limit: 15, }) if err != nil { - t.Error("Binance GetRecentTrades() error", err) + t.Error("Binance GetMostRecentTrades() error", err) } } @@ -977,3 +977,27 @@ func TestBinance_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSDT") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSDT") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go index a6eb57b2..bc5e2a92 100644 --- a/exchanges/binance/binance_types.go +++ b/exchanges/binance/binance_types.go @@ -116,7 +116,7 @@ type RecentTrade struct { ID int64 `json:"id"` Price float64 `json:"price,string"` Quantity float64 `json:"qty,string"` - Time float64 `json:"time"` + Time int64 `json:"time"` IsBuyerMaker bool `json:"isBuyerMaker"` IsBestMatch bool `json:"isBestMatch"` } diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go index 2b58b288..f4c2dac1 100644 --- a/exchanges/binance/binance_websocket.go +++ b/exchanges/binance/binance_websocket.go @@ -17,6 +17,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -264,41 +265,45 @@ func (b *Binance) wsHandleData(respRaw []byte) error { switch streamType[1] { case "trade": - var trade TradeStream - err := json.Unmarshal(rawData, &trade) + if !b.IsSaveTradeDataEnabled() { + return nil + } + var t TradeStream + err := json.Unmarshal(rawData, &t) if err != nil { return fmt.Errorf("%v - Could not unmarshal trade data: %s", b.Name, err) } - price, err := strconv.ParseFloat(trade.Price, 64) + price, err := strconv.ParseFloat(t.Price, 64) if err != nil { return fmt.Errorf("%v - price conversion error: %s", b.Name, err) } - amount, err := strconv.ParseFloat(trade.Quantity, 64) + amount, err := strconv.ParseFloat(t.Quantity, 64) if err != nil { return fmt.Errorf("%v - amount conversion error: %s", b.Name, err) } - pair, err := currency.NewPairFromFormattedPairs(trade.Symbol, pairs, format) + pair, err := currency.NewPairFromFormattedPairs(t.Symbol, pairs, format) if err != nil { return err } - b.Websocket.DataHandler <- stream.TradeData{ + return b.AddTradesToBuffer(trade.Data{ CurrencyPair: pair, - Timestamp: time.Unix(0, trade.TimeStamp*int64(time.Millisecond)), + Timestamp: time.Unix(0, t.TimeStamp*int64(time.Millisecond)), Price: price, Amount: amount, Exchange: b.Name, AssetType: asset.Spot, - } + TID: strconv.FormatInt(t.TradeID, 10), + }) case "ticker": var t TickerStream err := json.Unmarshal(rawData, &t) diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 9a100fcd..b6708539 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -2,6 +2,7 @@ package binance import ( "errors" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -496,9 +498,44 @@ func (b *Binance) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Binance) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Binance) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + limit := 1000 + tradeData, err := b.GetMostRecentTrades(RecentTradeRequestParams{p.String(), limit}) + if err != nil { + return nil, err + } + for i := range tradeData { + resp = append(resp, trade.Data{ + TID: strconv.FormatInt(tradeData[i].ID, 10), + Exchange: b.Name, + CurrencyPair: p, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Quantity, + Timestamp: time.Unix(0, tradeData[i].Time*int64(time.Millisecond)), + }) + } + if b.IsSaveTradeDataEnabled() { + err := trade.AddTradesToBuffer(b.Name, resp...) + if err != nil { + return nil, err + } + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Binance) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index dc079db9..687f1d9e 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -223,10 +223,11 @@ func (b *Bitfinex) GetTrades(currencyPair string, limit, timestampStart, timesta if timestampEnd > 0 { v.Set("end", strconv.FormatInt(timestampEnd, 10)) } - + sortVal := "0" if reOrderResp { - v.Set("sort", strconv.FormatInt(-1, 10)) + sortVal = "1" } + v.Set("sort", sortVal) path := b.API.Endpoints.URL + bitfinexAPIVersion2 + diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index a125613d..951f8dbc 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -1361,6 +1361,40 @@ func TestFixCasing(t *testing.T) { if ret != "tTNBUSD" { t.Errorf("unexpected result: %v", ret) } + pair, err = currency.NewPairFromStrings("fUSD", "") + if err != nil { + t.Fatal(err) + } + ret, err = b.fixCasing(pair, asset.Margin) + if err != nil { + t.Fatal(err) + } + if ret != "fUSD" { + t.Errorf("unexpected result: %v", ret) + } + pair, err = currency.NewPairFromStrings("USD", "") + if err != nil { + t.Fatal(err) + } + ret, err = b.fixCasing(pair, asset.Margin) + if err != nil { + t.Fatal(err) + } + if ret != "fUSD" { + t.Errorf("unexpected result: %v", ret) + } + + pair, err = currency.NewPairFromStrings("FUSD", "") + if err != nil { + t.Fatal(err) + } + ret, err = b.fixCasing(pair, asset.Margin) + if err != nil { + t.Fatal(err) + } + if ret != "fUSD" { + t.Errorf("unexpected result: %v", ret) + } } func Test_FormatExchangeKlineInterval(t *testing.T) { @@ -1401,3 +1435,42 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } + + currencyPair, err = currency.NewPairFromString("USD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Margin) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil { + t.Error(err) + } + + // longer term test + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Hour*24*100), time.Now().Add(-time.Hour*24*99)) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/bitfinex/bitfinex_types.go b/exchanges/bitfinex/bitfinex_types.go index e79a1f32..2c68ef21 100644 --- a/exchanges/bitfinex/bitfinex_types.go +++ b/exchanges/bitfinex/bitfinex_types.go @@ -315,7 +315,7 @@ type MovementHistory struct { type TradeHistory struct { Price float64 `json:"price,string"` Amount float64 `json:"amount,string"` - Timestamp string `json:"timestamp"` + Timestamp int64 `json:"timestamp"` Exchange string `json:"exchange"` Type string `json:"type"` FeeCurrency string `json:"fee_currency"` diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index 5a227627..bb5eb258 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -198,7 +199,9 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { if !ok { return errors.New("orderbook interface cast failed") } - + if len(obSnapBundle) == 0 { + return errors.New("no data within orderbook snapshot") + } switch id := obSnapBundle[0].(type) { case []interface{}: for i := range obSnapBundle { @@ -296,14 +299,20 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } return nil case wsTrades: - var trades []WebsocketTrade + if !b.IsSaveTradeDataEnabled() { + return nil + } + if chanAsset == asset.MarginFunding { + return nil + } + var tradeHolder []WebsocketTrade switch len(d) { case 2: snapshot := d[1].([]interface{}) for i := range snapshot { elem := snapshot[i].([]interface{}) if len(elem) == 5 { - trades = append(trades, WebsocketTrade{ + tradeHolder = append(tradeHolder, WebsocketTrade{ ID: int64(elem[0].(float64)), Timestamp: int64(elem[1].(float64)), Amount: elem[2].(float64), @@ -311,7 +320,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { Period: int64(elem[4].(float64)), }) } else { - trades = append(trades, WebsocketTrade{ + tradeHolder = append(tradeHolder, WebsocketTrade{ ID: int64(elem[0].(float64)), Timestamp: int64(elem[1].(float64)), Amount: elem[2].(float64), @@ -320,16 +329,13 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { } } case 3: - if d[1].(string) == wsTradeExecutionUpdate || - d[1].(string) == wsFundingTradeUpdate { - // "(f)te - trade executed" && "(f)tu - trade updated" - // contain the same amount of data - // "(f)te" gets sent first so we can drop "(f)tu" + if d[1].(string) != wsFundingTradeUpdate && + d[1].(string) != wsTradeExecutionUpdate { return nil } data := d[2].([]interface{}) if len(data) == 5 { - trades = append(trades, WebsocketTrade{ + tradeHolder = append(tradeHolder, WebsocketTrade{ ID: int64(data[0].(float64)), Timestamp: int64(data[1].(float64)), Amount: data[2].(float64), @@ -337,7 +343,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { Period: int64(data[4].(float64)), }) } else { - trades = append(trades, WebsocketTrade{ + tradeHolder = append(tradeHolder, WebsocketTrade{ ID: int64(data[0].(float64)), Timestamp: int64(data[1].(float64)), Amount: data[2].(float64), @@ -345,40 +351,31 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error { }) } } - - for i := range trades { + var trades []trade.Data + for i := range tradeHolder { side := order.Buy - newAmount := trades[i].Amount + newAmount := tradeHolder[i].Amount if newAmount < 0 { side = order.Sell newAmount *= -1 } - - if trades[i].Rate > 0 { - b.Websocket.DataHandler <- stream.FundingData{ - CurrencyPair: pair, - Timestamp: time.Unix(0, trades[i].Timestamp*int64(time.Millisecond)), - Amount: newAmount, - Exchange: b.Name, - AssetType: chanAsset, - Side: side, - Rate: trades[i].Rate, - Period: trades[i].Period, - } - continue + price := tradeHolder[i].Price + if price == 0 && tradeHolder[i].Rate > 0 { + price = tradeHolder[i].Rate } - - b.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ + TID: strconv.FormatInt(tradeHolder[i].ID, 10), CurrencyPair: pair, - Timestamp: time.Unix(0, trades[i].Timestamp*int64(time.Millisecond)), - Price: trades[i].Price, + Timestamp: time.Unix(0, tradeHolder[i].Timestamp*int64(time.Millisecond)), + Price: price, Amount: newAmount, Exchange: b.Name, AssetType: chanAsset, Side: side, - } + }) } - return nil + + return b.AddTradesToBuffer(trades...) } if authResp, ok := d[1].(string); ok { diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 7835c034..77e2ebf9 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -2,6 +2,8 @@ package bitfinex import ( "errors" + "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -481,9 +484,74 @@ func (b *Bitfinex) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bitfinex) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Bitfinex) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bitfinex) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if assetType == asset.MarginFunding { + return nil, fmt.Errorf("asset type '%v' not supported", assetType) + } + if timestampStart.Equal(timestampEnd) || timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var currString string + currString, err = b.fixCasing(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + ts := timestampEnd + limit := 10000 +allTrades: + for { + var tradeData []Trade + tradeData, err = b.GetTrades(currString, int64(limit), 0, ts.Unix()*1000, false) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTS := time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond)) + if tradeTS.Before(timestampStart) && !timestampStart.IsZero() { + break allTrades + } + tID := strconv.FormatInt(tradeData[i].TID, 10) + resp = append(resp, trade.Data{ + TID: tID, + Exchange: b.Name, + CurrencyPair: p, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond)), + }) + if i == len(tradeData)-1 { + if ts.Equal(tradeTS) { + // reached end of trades to crawl + break allTrades + } + ts = tradeTS + } + } + if len(tradeData) != limit { + break allTrades + } + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return trade.FilterTradesByTime(resp, timestampStart, timestampEnd), nil } // SubmitOrder submits a new order @@ -965,10 +1033,16 @@ func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) (string, error) { y := in.Base.String() if (y[0] != checkString[0] && y[0] != checkString[1]) || (y[0] == checkString[1] && y[1] == checkString[1]) || in.Base == currency.TNB { + if fmt.Quote.IsEmpty() { + return string(checkString[0]) + fmt.Base.Upper().String(), nil + } return string(checkString[0]) + fmt.Upper().String(), nil } runes := []rune(fmt.Upper().String()) + if fmt.Quote.IsEmpty() { + runes = []rune(fmt.Base.Upper().String()) + } runes[0] = unicode.ToLower(runes[0]) return string(runes), nil } diff --git a/exchanges/bitflyer/bitflyer_test.go b/exchanges/bitflyer/bitflyer_test.go index 47f95964..632ef052 100644 --- a/exchanges/bitflyer/bitflyer_test.go +++ b/exchanges/bitflyer/bitflyer_test.go @@ -4,6 +4,7 @@ import ( "log" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" @@ -25,7 +26,6 @@ const ( var b Bitflyer func TestMain(m *testing.M) { - b.SetDefaults() cfg := config.GetConfig() err := cfg.LoadConfig("../../testdata/configtest.json", true) if err != nil { @@ -39,7 +39,7 @@ func TestMain(m *testing.M) { bitflyerConfig.API.AuthenticatedSupport = true bitflyerConfig.API.Credentials.Key = apiKey bitflyerConfig.API.Credentials.Secret = apiSecret - + b.SetDefaults() err = b.Setup(bitflyerConfig) if err != nil { log.Fatal("Bitflyer setup error", err) @@ -431,3 +431,27 @@ func TestWithdrawInternationalBank(t *testing.T) { t.Errorf("Expected '%v', received: '%v'", common.ErrNotYetImplemented, err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_JPY") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_JPY") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Fatal(err) + } +} diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go index 1c061971..ad1c3988 100644 --- a/exchanges/bitflyer/bitflyer_wrapper.go +++ b/exchanges/bitflyer/bitflyer_wrapper.go @@ -1,6 +1,8 @@ package bitflyer import ( + "sort" + "strconv" "strings" "sync" "time" @@ -17,6 +19,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -301,9 +304,53 @@ func (b *Bitflyer) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bitflyer) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns recent historic trades +func (b *Bitflyer) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + tradeData, err := b.GetExecutionHistory(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + var timestamp time.Time + timestamp, err = time.Parse("2006-01-02T15:04:05.999999999", tradeData[i].ExecDate) + if err != nil { + return nil, err + } + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + TID: strconv.FormatInt(tradeData[i].ID, 10), + Exchange: b.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Size, + Timestamp: timestamp, + }) + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bitflyer) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/bithumb/bithumb_test.go b/exchanges/bithumb/bithumb_test.go index a2e57a3d..f2c5f929 100644 --- a/exchanges/bithumb/bithumb_test.go +++ b/exchanges/bithumb/bithumb_test.go @@ -596,3 +596,27 @@ func TestGetHistoricCandlesExtended(t *testing.T) { t.Fatal(err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_KRW") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_KRW") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index 12c3c0d4..9caefd78 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "sort" "strconv" "sync" "time" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -329,9 +331,52 @@ func (b *Bithumb) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bithumb) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Bithumb) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + tradeData, err := b.GetTransactionHistory(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData.Data { + var side order.Side + side, err = order.StringToOrderSide(tradeData.Data[i].Type) + if err != nil { + return nil, err + } + var t time.Time + t, err = time.Parse("2006-01-02 15:04:05", tradeData.Data[i].TransactionDate) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData.Data[i].Price, + Amount: tradeData.Data[i].UnitsTraded, + Timestamp: t, + }) + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bithumb) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go index a271d948..828e4c9a 100644 --- a/exchanges/bitmex/bitmex_test.go +++ b/exchanges/bitmex/bitmex_test.go @@ -51,6 +51,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatal("Bitmex setup error", err) } + b.UpdateTradablePairs(true) os.Exit(m.Run()) } @@ -361,9 +362,10 @@ func TestGetStatSummary(t *testing.T) { func TestGetTrade(t *testing.T) { _, err := b.GetTrade(&GenericRequestParams{ - Symbol: "ETHUSD", - StartTime: time.Now().Format(time.RFC3339), - Reverse: true}) + Symbol: "XBT", + Reverse: false, + StartTime: time.Now().Add(-time.Hour).Format(time.RFC3339), + }) if err != nil { t.Error("GetTrade() error", err) } @@ -935,3 +937,29 @@ func TestWsTrades(t *testing.T) { t.Error(err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + err := b.UpdateTradablePairs(false) + if err != nil { + t.Fatal(err) + } + currencyPair := b.CurrencyPairs.Pairs[asset.Futures].Available[0] + _, err = b.GetRecentTrades(currencyPair, asset.Futures) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + err := b.UpdateTradablePairs(false) + if err != nil { + t.Fatal(err) + } + currencyPair := b.CurrencyPairs.Pairs[asset.Futures].Available[0] + _, err = b.GetHistoricTrades(currencyPair, asset.Futures, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go index 59e0ac17..b4562ad7 100644 --- a/exchanges/bitmex/bitmex_websocket.go +++ b/exchanges/bitmex/bitmex_websocket.go @@ -18,6 +18,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -214,15 +215,23 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error { } case bitmexWSTrade: - var trades TradeData - err = json.Unmarshal(respRaw, &trades) + if !b.IsSaveTradeDataEnabled() { + return nil + } + var tradeHolder TradeData + err = json.Unmarshal(respRaw, &tradeHolder) if err != nil { return err } - - for i := range trades.Data { + var trades []trade.Data + for i := range tradeHolder.Data { + if tradeHolder.Data[i].Price == 0 { + // Please note that indices (symbols starting with .) post trades at intervals to the trade feed. + // These have a size of 0 and are used only to indicate a changing price. + continue + } var p currency.Pair - p, err = currency.NewPairFromString(trades.Data[i].Symbol) + p, err = currency.NewPairFromString(tradeHolder.Data[i].Symbol) if err != nil { return err } @@ -233,7 +242,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error { return err } var oSide order.Side - oSide, err = order.StringToOrderSide(trades.Data[i].Side) + oSide, err = order.StringToOrderSide(tradeHolder.Data[i].Side) if err != nil { b.Websocket.DataHandler <- order.ClassificationError{ Exchange: b.Name, @@ -241,17 +250,18 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error { } } - b.Websocket.DataHandler <- stream.TradeData{ - Timestamp: trades.Data[i].Timestamp, - Price: trades.Data[i].Price, - Amount: float64(trades.Data[i].Size), - CurrencyPair: p, + trades = append(trades, trade.Data{ + TID: tradeHolder.Data[i].TrdMatchID, Exchange: b.Name, + CurrencyPair: p, AssetType: a, Side: oSide, - } + Price: tradeHolder.Data[i].Price, + Amount: float64(tradeHolder.Data[i].Size), + Timestamp: tradeHolder.Data[i].Timestamp, + }) } - + return b.AddTradesToBuffer(trades...) case bitmexWSAnnouncement: var announcement AnnouncementData err = json.Unmarshal(respRaw, &announcement) diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index 9ac062dc..3b0beae0 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -2,7 +2,9 @@ package bitmex import ( "errors" + "fmt" "math" + "sort" "strings" "sync" "time" @@ -20,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -420,9 +423,83 @@ func (b *Bitmex) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrNotYetImplemented } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bitmex) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Bitmex) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bitmex) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if assetType == asset.Index { + return nil, fmt.Errorf("asset type '%v' not supported", assetType) + } + if timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + limit := 1000 + req := &GenericRequestParams{ + Symbol: p.String(), + Count: int32(limit), + EndTime: timestampEnd.UTC().Format("2006-01-02T15:04:05.000Z"), + } + ts := timestampStart + var resp []trade.Data +allTrades: + for { + req.StartTime = ts.UTC().Format("2006-01-02T15:04:05.000Z") + var tradeData []Trade + tradeData, err = b.GetTrade(req) + if err != nil { + return nil, err + } + for i := range tradeData { + if tradeData[i].Timestamp.Before(timestampStart) || tradeData[i].Timestamp.After(timestampEnd) { + break allTrades + } + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + if tradeData[i].Price == 0 { + // Please note that indices (symbols starting with .) post trades at intervals to the trade feed. + // These have a size of 0 and are used only to indicate a changing price. + continue + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: float64(tradeData[i].Size), + Timestamp: tradeData[i].Timestamp, + TID: tradeData[i].TrdMatchID, + }) + if i == len(tradeData)-1 { + if ts.Equal(tradeData[i].Timestamp) { + // reached end of trades to crawl + break allTrades + } + ts = tradeData[i].Timestamp + } + } + if len(tradeData) != limit { + break allTrades + } + } + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return trade.FilterTradesByTime(resp, timestampStart, timestampEnd), nil } // SubmitOrder submits a new order diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index ca88a128..337e630e 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -231,21 +231,21 @@ func (b *Bitstamp) GetTradingPairs() ([]TradingPair, error) { // GetTransactions returns transaction information // value paramater ["time"] = "minute", "hour", "day" will collate your -// response into time intervals. Implementation of value in test code. -func (b *Bitstamp) GetTransactions(currencyPair string, values url.Values) ([]Transactions, error) { +// response into time intervals. +func (b *Bitstamp) GetTransactions(currencyPair, timePeriod string) ([]Transactions, error) { var transactions []Transactions - path := common.EncodeURLValues( - fmt.Sprintf( - "%s/v%s/%s/%s/", - b.API.Endpoints.URL, - bitstampAPIVersion, - bitstampAPITransactions, - strings.ToLower(currencyPair), - ), - values, + requestURL := fmt.Sprintf( + "%s/v%s/%s/%s/", + b.API.Endpoints.URL, + bitstampAPIVersion, + bitstampAPITransactions, + strings.ToLower(currencyPair), ) + if timePeriod != "" { + requestURL += "?time=" + url.QueryEscape(timePeriod) + } - return transactions, b.SendHTTPRequest(path, &transactions) + return transactions, b.SendHTTPRequest(requestURL, &transactions) } // GetEURUSDConversionRate returns the conversion rate between Euro and USD diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go index 7aebbf34..389164e2 100644 --- a/exchanges/bitstamp/bitstamp_test.go +++ b/exchanges/bitstamp/bitstamp_test.go @@ -1,10 +1,10 @@ package bitstamp import ( - "net/url" "testing" "time" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/core" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" @@ -200,11 +200,7 @@ func TestGetTradingPairs(t *testing.T) { func TestGetTransactions(t *testing.T) { t.Parallel() - - value := url.Values{} - value.Set("time", "hour") - - _, err := b.GetTransactions(currency.BTC.String()+currency.USD.String(), value) + _, err := b.GetTransactions(currency.BTC.String()+currency.USD.String(), "hour") if err != nil { t.Error("GetTransactions() error", err) } @@ -705,3 +701,27 @@ func TestBitstamp_GetHistoricCandlesExtended(t *testing.T) { t.Fatal(err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("LTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("LTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/bitstamp/bitstamp_types.go b/exchanges/bitstamp/bitstamp_types.go index dfe6982e..8d9949d9 100644 --- a/exchanges/bitstamp/bitstamp_types.go +++ b/exchanges/bitstamp/bitstamp_types.go @@ -205,7 +205,7 @@ type websocketTradeData struct { Timestamp int64 `json:"timestamp,string"` Price float64 `json:"price"` Type int `json:"type"` - ID int `json:"id"` + ID int64 `json:"id"` } type websocketOrderBookResponse struct { diff --git a/exchanges/bitstamp/bitstamp_websocket.go b/exchanges/bitstamp/bitstamp_websocket.go index 7d8b72ce..9c13c3ac 100644 --- a/exchanges/bitstamp/bitstamp_websocket.go +++ b/exchanges/bitstamp/bitstamp_websocket.go @@ -15,6 +15,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -91,7 +92,7 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error { if err != nil { return err } - currencyPair := strings.Split(wsResponse.Channel, "_") + currencyPair := strings.Split(wsResponse.Channel, currency.UnderscoreDelimiter) p, err := currency.NewPairFromString(strings.ToUpper(currencyPair[2])) if err != nil { return err @@ -102,19 +103,22 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error { return err } case "trade": + if !b.IsSaveTradeDataEnabled() { + return nil + } wsTradeTemp := websocketTradeResponse{} err := json.Unmarshal(respRaw, &wsTradeTemp) if err != nil { return err } - currencyPair := strings.Split(wsResponse.Channel, "_") + currencyPair := strings.Split(wsResponse.Channel, currency.UnderscoreDelimiter) p, err := currency.NewPairFromString(strings.ToUpper(currencyPair[2])) if err != nil { return err } side := order.Buy - if wsTradeTemp.Data.Type == -1 { + if wsTradeTemp.Data.Type == 1 { side = order.Sell } var a asset.Item @@ -122,16 +126,16 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error { if err != nil { return err } - b.Websocket.DataHandler <- stream.TradeData{ + return trade.AddTradesToBuffer(b.Name, trade.Data{ Timestamp: time.Unix(wsTradeTemp.Data.Timestamp, 0), CurrencyPair: p, AssetType: a, Exchange: b.Name, - EventType: order.UnknownType, Price: wsTradeTemp.Data.Price, Amount: wsTradeTemp.Data.Amount, Side: side, - } + TID: strconv.FormatInt(wsTradeTemp.Data.ID, 10), + }) case "order_created", "order_deleted", "order_changed": if b.Verbose { log.Debugf(log.ExchangeSys, "%v - Websocket order acknowledgement", b.Name) diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 0a9554df..43539def 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -2,6 +2,7 @@ package bitstamp import ( "errors" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -396,9 +398,48 @@ func (b *Bitstamp) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bitstamp) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Bitstamp) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData []Transactions + tradeData, err = b.GetTransactions(p.String(), "") + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + s := order.Buy + if tradeData[i].Type == 1 { + s = order.Sell + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + TID: strconv.FormatInt(tradeData[i].TradeID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: s, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: time.Unix(tradeData[i].Date, 0), + }) + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bitstamp) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go index 8511df0f..c853e1ed 100644 --- a/exchanges/bittrex/bittrex_test.go +++ b/exchanges/bittrex/bittrex_test.go @@ -4,6 +4,7 @@ import ( "log" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" @@ -550,3 +551,27 @@ func TestParseTime(t *testing.T) { t.Error("invalid time values") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(currPair) + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(currPair) + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Fatal(err) + } +} diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 72ef35bb..7f506ba6 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -2,6 +2,8 @@ package bittrex import ( "errors" + "sort" + "strconv" "strings" "sync" "time" @@ -18,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -372,9 +375,53 @@ func (b *Bittrex) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *Bittrex) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *Bittrex) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + tradeData, err := b.GetMarketHistory(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData.Result { + var side order.Side + side, err = order.StringToOrderSide(tradeData.Result[i].OrderType) + if err != nil { + return nil, err + } + var ts time.Time + ts, err = time.Parse("2006-01-02T15:04:05.999999999", tradeData.Result[i].Timestamp) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + TID: strconv.FormatInt(tradeData.Result[i].ID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData.Result[i].Price, + Amount: tradeData.Result[i].Quantity, + Timestamp: ts, + }) + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *Bittrex) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index 02988dff..9d40f339 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -102,7 +102,7 @@ func (b *BTCMarkets) GetTrades(marketID string, before, after, limit int64) ([]T if before > 0 { params.Set("before", strconv.FormatInt(before, 10)) } - if after >= 0 { + if after > 0 { params.Set("after", strconv.FormatInt(after, 10)) } if limit > 0 { diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index 0a44710a..ac248cb5 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -777,3 +778,27 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-AUD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-AUD") + if err != nil { + t.Fatal(err) + } + _, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go index 7fe37656..d7b0c5c5 100644 --- a/exchanges/btcmarkets/btcmarkets_websocket.go +++ b/exchanges/btcmarkets/btcmarkets_websocket.go @@ -18,6 +18,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -142,32 +143,35 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { return err } case tradeEndPoint: - var trade WsTrade - err := json.Unmarshal(respRaw, &trade) + if !b.IsSaveTradeDataEnabled() { + return nil + } + var t WsTrade + err := json.Unmarshal(respRaw, &t) if err != nil { return err } - p, err := currency.NewPairFromString(trade.Currency) + p, err := currency.NewPairFromString(t.Currency) if err != nil { return err } side := order.Buy - if trade.Side == "Ask" { + if t.Side == "Ask" { side = order.Sell } - b.Websocket.DataHandler <- stream.TradeData{ - Timestamp: trade.Timestamp, + return trade.AddTradesToBuffer(b.Name, trade.Data{ + Timestamp: t.Timestamp, CurrencyPair: p, AssetType: asset.Spot, Exchange: b.Name, - Price: trade.Price, - Amount: trade.Volume, + Price: t.Price, + Amount: t.Volume, Side: side, - EventType: order.UnknownType, - } + TID: strconv.FormatInt(t.TradeID, 10), + }) case tick: var tick WsTick err := json.Unmarshal(respRaw, &tick) diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 36a6b3f8..35ff90a9 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -3,6 +3,7 @@ package btcmarkets import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -424,9 +426,51 @@ func (b *BTCMarkets) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *BTCMarkets) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *BTCMarkets) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + var tradeData []Trade + tradeData, err = b.GetTrades(p.String(), 0, 0, 200) + if err != nil { + return nil, err + } + for i := range tradeData { + side := order.Side("") + if tradeData[i].Side != "" { + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + TID: tradeData[i].TradeID, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeData[i].Timestamp, + }) + } + + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *BTCMarkets) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/btse/btse.go b/exchanges/btse/btse.go index 8f20b1bb..bf0faaea 100644 --- a/exchanges/btse/btse.go +++ b/exchanges/btse/btse.go @@ -94,20 +94,22 @@ func (b *BTSE) FetchOrderBookL2(symbol string, depth int) (*Orderbook, error) { } // GetTrades returns a list of trades for the specified symbol -func (b *BTSE) GetTrades(symbol string, start, end time.Time, beforeSerialID, afterSerialID, count int, includeOld bool) ([]Trade, error) { +func (b *BTSE) GetTrades(symbol string, start, end time.Time, beforeSerialID, afterSerialID, count int, includeOld, spot bool) ([]Trade, error) { var t []Trade urlValues := url.Values{} urlValues.Add("symbol", symbol) if count > 0 { urlValues.Add("count", strconv.Itoa(count)) } - if !start.IsZero() && !end.IsZero() { - if start.After(end) { - return t, errors.New("start cannot be after end time") - } + if !start.IsZero() { urlValues.Add("start", strconv.FormatInt(start.Unix(), 10)) + } + if !end.IsZero() { urlValues.Add("end", strconv.FormatInt(end.Unix(), 10)) } + if !start.IsZero() && !end.IsZero() && start.After(end) { + return t, errors.New("start cannot be after end time") + } if beforeSerialID > 0 { urlValues.Add("beforeSerialId", strconv.Itoa(beforeSerialID)) } @@ -118,7 +120,7 @@ func (b *BTSE) GetTrades(symbol string, start, end time.Time, beforeSerialID, af urlValues.Add("includeOld", "true") } return t, b.SendHTTPRequest(http.MethodGet, - common.EncodeURLValues(btseTrades, urlValues), &t, true, queryFunc) + common.EncodeURLValues(btseTrades, urlValues), &t, spot, queryFunc) } // OHLCV retrieve and return OHLCV candle data for requested symbol diff --git a/exchanges/btse/btse_test.go b/exchanges/btse/btse_test.go index a1969203..f9111d4c 100644 --- a/exchanges/btse/btse_test.go +++ b/exchanges/btse/btse_test.go @@ -24,7 +24,8 @@ const ( apiKey = "" apiSecret = "" canManipulateRealOrders = false - testPair = "BTC-USD" + testSPOTPair = "BTC-USD" + testFUTURESPair = "BTCPFC" ) var b BTSE @@ -63,7 +64,7 @@ func TestGetMarketsSummary(t *testing.T) { t.Error(err) } - ret, err := b.GetMarketSummary(testPair, true) + ret, err := b.GetMarketSummary(testSPOTPair, true) if err != nil { t.Error(err) } @@ -74,17 +75,17 @@ func TestGetMarketsSummary(t *testing.T) { func TestFetchOrderBook(t *testing.T) { t.Parallel() - _, err := b.FetchOrderBook(testPair, 0, 1, 1, true) + _, err := b.FetchOrderBook(testSPOTPair, 0, 1, 1, true) if err != nil { t.Error(err) } - _, err = b.FetchOrderBook("BTCPFC", 0, 1, 1, false) + _, err = b.FetchOrderBook(testFUTURESPair, 0, 1, 1, false) if err != nil { t.Error(err) } - _, err = b.FetchOrderBook(testPair, 1, 1, 1, true) + _, err = b.FetchOrderBook(testSPOTPair, 1, 1, 1, true) if err != nil { t.Error(err) } @@ -93,7 +94,7 @@ func TestFetchOrderBook(t *testing.T) { func TestUpdateOrderbook(t *testing.T) { t.Parallel() - p, err := currency.NewPairFromString(testPair) + p, err := currency.NewPairFromString(testSPOTPair) if err != nil { t.Fatal(err) } @@ -116,7 +117,7 @@ func TestUpdateOrderbook(t *testing.T) { func TestFetchOrderBookL2(t *testing.T) { t.Parallel() - _, err := b.FetchOrderBookL2(testPair, 20) + _, err := b.FetchOrderBookL2(testSPOTPair, 20) if err != nil { t.Error(err) } @@ -124,14 +125,14 @@ func TestFetchOrderBookL2(t *testing.T) { func TestOHLCV(t *testing.T) { t.Parallel() - _, err := b.OHLCV(testPair, + _, err := b.OHLCV(testSPOTPair, time.Now().AddDate(0, 0, -1), time.Now(), 60) if err != nil { t.Fatal(err) } - _, err = b.OHLCV(testPair, time.Now(), time.Now().AddDate(0, 0, -1), 60) + _, err = b.OHLCV(testSPOTPair, time.Now(), time.Now().AddDate(0, 0, -1), 60) if err == nil { t.Fatal("expected error if start is after end date") } @@ -139,7 +140,7 @@ func TestOHLCV(t *testing.T) { func TestGetPrice(t *testing.T) { t.Parallel() - _, err := b.GetPrice(testPair) + _, err := b.GetPrice(testSPOTPair) if err != nil { t.Fatal(err) } @@ -154,7 +155,7 @@ func TestFormatExchangeKlineInterval(t *testing.T) { func TestGetHistoricCandles(t *testing.T) { t.Parallel() - curr, err := currency.NewPairFromString(testPair) + curr, err := currency.NewPairFromString(testSPOTPair) if err != nil { t.Fatal(err) } @@ -187,7 +188,7 @@ func TestGetHistoricCandles(t *testing.T) { func TestGetHistoricCandlesExtended(t *testing.T) { t.Parallel() - curr, err := currency.NewPairFromString(testPair) + curr, err := currency.NewPairFromString(testSPOTPair) if err != nil { t.Fatal(err) } @@ -203,24 +204,31 @@ func TestGetHistoricCandlesExtended(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := b.GetTrades(testPair, + _, err := b.GetTrades(testSPOTPair, time.Now().AddDate(0, 0, -1), time.Now(), - 0, 0, 50, false) + 0, 0, 50, false, true) if err != nil { t.Error(err) } - _, err = b.GetTrades(testPair, + _, err = b.GetTrades(testSPOTPair, time.Now(), time.Now().AddDate(0, -1, 0), - 0, 0, 50, false) + 0, 0, 50, false, true) if err == nil { t.Error("expected error if start time is after end time") } + + _, err = b.GetTrades(testFUTURESPair, + time.Now().AddDate(0, 0, -1), time.Now(), + 0, 0, 50, false, false) + if err != nil { + t.Error(err) + } } func TestUpdateTicker(t *testing.T) { t.Parallel() - curr, err := currency.NewPairFromString(testPair) + curr, err := currency.NewPairFromString(testSPOTPair) if err != nil { t.Fatal(err) } @@ -276,7 +284,7 @@ func TestGetWalletHistory(t *testing.T) { if !areTestAPIKeysSet() { t.Skip("API keys not set, skipping test") } - _, err := b.GetWalletHistory(testPair, + _, err := b.GetWalletHistory(testSPOTPair, time.Time{}, time.Time{}, 50) if err != nil { @@ -325,7 +333,7 @@ func TestCreateOrder(t *testing.T) { _, err := b.CreateOrder("", 0.0, false, -1, "BUY", 100, 0, 0, - testPair, "GTC", + testSPOTPair, "GTC", 0.0, 0.0, "LIMIT", "LIMIT") if err != nil { @@ -341,7 +349,7 @@ func TestBTSEIndexOrderPeg(t *testing.T) { _, err := b.IndexOrderPeg("", 0.0, false, -1, "BUY", 100, 0, 0, - testPair, "GTC", + testSPOTPair, "GTC", 0.0, 0.0, "", "LIMIT") if err != nil { @@ -354,7 +362,7 @@ func TestGetOrders(t *testing.T) { if !areTestAPIKeysSet() { t.Skip("API keys not set, skipping test") } - _, err := b.GetOrders(testPair, "", "") + _, err := b.GetOrders(testSPOTPair, "", "") if err != nil { t.Error(err) } @@ -387,21 +395,6 @@ func TestGetActiveOrders(t *testing.T) { } } -func TestGetExchangeHistory(t *testing.T) { - curr, _ := currency.NewPairFromString(testPair) - _, err := b.GetExchangeHistory(curr, asset.Spot, time.Now().AddDate(0, -6, 0), time.Now()) - if err != nil { - t.Fatal(err) - } - - _, err = b.GetExchangeHistory(curr, asset.Futures, time.Now().AddDate(0, -6, 0), time.Now()) - if err != nil { - if !errors.Is(err, common.ErrNotYetImplemented) { - t.Fatal(err) - } - } -} - func TestGetOrderHistory(t *testing.T) { t.Parallel() if !areTestAPIKeysSet() { @@ -597,7 +590,7 @@ func TestCancelOrder(t *testing.T) { if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false") } - _, err := b.CancelExistingOrder("", testPair, "") + _, err := b.CancelExistingOrder("", testSPOTPair, "") if err != nil { t.Fatal(err) } @@ -729,7 +722,7 @@ func TestSeedOrderSizeLimits(t *testing.T) { func TestOrderSizeLimits(t *testing.T) { t.Parallel() seedOrderSizeLimitMap() - _, ok := OrderSizeLimits(testPair) + _, ok := OrderSizeLimits(testSPOTPair) if !ok { t.Fatal("expected BTC-USD to be found in map") } @@ -823,3 +816,36 @@ func TestWithinLimits(t *testing.T) { t.Fatal("expected invalid limits") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testSPOTPair) + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } + currencyPair, err = currency.NewPairFromString(testFUTURESPair) + if err != nil { + t.Fatal(err) + } + _, err = b.GetRecentTrades(currencyPair, asset.Futures) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + curr, _ := currency.NewPairFromString(testSPOTPair) + + _, err := b.GetHistoricTrades(curr, asset.Spot, time.Now().Add(-time.Minute), time.Now()) + if err == nil { + t.Fatal("expected error") + } + if err != common.ErrFunctionNotSupported { + t.Error("unexpected error") + } +} diff --git a/exchanges/btse/btse_types.go b/exchanges/btse/btse_types.go index f98570bc..63020de7 100644 --- a/exchanges/btse/btse_types.go +++ b/exchanges/btse/btse_types.go @@ -112,7 +112,7 @@ type FuturesMarket struct { // Trade stores trade data type Trade struct { - SerialID int `json:"serialId"` + SerialID int64 `json:"serialId"` Symbol string `json:"symbol"` Price float64 `json:"price"` Amount float64 `json:"size"` diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go index 743b70e8..bb5a452d 100644 --- a/exchanges/btse/btse_websocket.go +++ b/exchanges/btse/btse_websocket.go @@ -17,6 +17,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" ) const ( @@ -185,13 +186,16 @@ func (b *BTSE) wsHandleData(respRaw []byte) error { Pair: p, } } - case strings.Contains(result["topic"].(string), "tradeHistory"): + if !b.IsSaveTradeDataEnabled() { + return nil + } var tradeHistory wsTradeHistory err = json.Unmarshal(respRaw, &tradeHistory) if err != nil { return err } + var trades []trade.Data for x := range tradeHistory.Data { side := order.Buy if tradeHistory.Data[x].Gain == -1 { @@ -211,7 +215,7 @@ func (b *BTSE) wsHandleData(respRaw []byte) error { if err != nil { return err } - b.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ Timestamp: time.Unix(0, tradeHistory.Data[x].TransactionTime*int64(time.Millisecond)), CurrencyPair: p, AssetType: a, @@ -219,8 +223,10 @@ func (b *BTSE) wsHandleData(respRaw []byte) error { Price: tradeHistory.Data[x].Price, Amount: tradeHistory.Data[x].Amount, Side: side, - } + TID: strconv.FormatInt(tradeHistory.Data[x].ID, 10), + }) } + return trade.AddTradesToBuffer(b.Name, trades...) case strings.Contains(result["topic"].(string), "orderBookApi"): var t wsOrderBook err = json.Unmarshal(respRaw, &t) @@ -261,7 +267,7 @@ func (b *BTSE) wsHandleData(respRaw []byte) error { Amount: amount, }) } - p, err := currency.NewPairFromString(t.Topic[strings.Index(t.Topic, ":")+1 : strings.Index(t.Topic, "_")]) + p, err := currency.NewPairFromString(t.Topic[strings.Index(t.Topic, ":")+1 : strings.Index(t.Topic, currency.UnderscoreDelimiter)]) if err != nil { return err } diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go index dec7d955..5f4c7eb9 100644 --- a/exchanges/btse/btse_wrapper.go +++ b/exchanges/btse/btse_wrapper.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "sort" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -396,41 +398,6 @@ func (b *BTSE) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (b *BTSE) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - if assetType != asset.Spot { - return nil, common.ErrNotYetImplemented - } - - fPair, err := b.FormatExchangeCurrency(p, assetType) - if err != nil { - return nil, err - } - - trades, err := b.GetTrades(fPair.String(), - timestampStart, timestampEnd, - 0, 0, 0, - false) - if err != nil { - return nil, err - } - var resp []exchange.TradeHistory - for x := range trades { - tempExch := exchange.TradeHistory{ - Timestamp: time.Unix(0, trades[x].Time*int64(time.Millisecond)), - Price: trades[x].Price, - Amount: trades[x].Amount, - Exchange: b.Name, - Side: trades[x].Side, - Type: trades[x].Type, - TID: strconv.Itoa(trades[x].SerialID), - } - - resp = append(resp, tempExch) - } - return resp, nil -} - func (b *BTSE) withinLimits(pair currency.Pair, amount float64) bool { val, found := OrderSizeLimits(pair.String()) if !found { @@ -441,6 +408,57 @@ func (b *BTSE) withinLimits(pair currency.Pair, amount float64) bool { amount > val.MaxOrderSize } +// GetRecentTrades returns the most recent trades for a currency and asset +func (b *BTSE) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = b.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + limit := 500 + + var tradeData []Trade + tradeData, err = b.GetTrades(p.String(), + time.Time{}, time.Time{}, + 0, 0, limit, + false, + assetType == asset.Spot) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTimestamp := time.Unix(tradeData[i].Time/1000, 0) + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: b.Name, + TID: strconv.FormatInt(tradeData[i].SerialID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTimestamp, + }) + } + err = b.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (b *BTSE) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported +} + // SubmitOrder submits a new order func (b *BTSE) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) { var resp order.SubmitResponse diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go index b48f01e4..72f42810 100644 --- a/exchanges/coinbasepro/coinbasepro_test.go +++ b/exchanges/coinbasepro/coinbasepro_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/gorilla/websocket" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/core" @@ -1008,3 +1009,27 @@ func TestCheckInterval(t *testing.T) { t.Fatal("error cannot be nil") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testPair) + if err != nil { + t.Fatal(err) + } + _, err = c.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testPair) + if err != nil { + t.Fatal(err) + } + _, err = c.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/coinbasepro/coinbasepro_websocket.go b/exchanges/coinbasepro/coinbasepro_websocket.go index 6dad3340..2f0e166c 100644 --- a/exchanges/coinbasepro/coinbasepro_websocket.go +++ b/exchanges/coinbasepro/coinbasepro_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" ) const ( @@ -130,11 +131,6 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { if err != nil { return err } - // the following cases contains data to synchronise authenticated orders - // subscribing to the "full" channel will consider ALL cbp orders as - // personal orders - // remove sending &order.Detail to the datahandler if you wish to subscribe to the - // "full" channel case "received", "open", "done", "change", "activate": var wsOrder wsOrderReceived err := json.Unmarshal(respRaw, &wsOrder) @@ -176,30 +172,32 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { ts = convert.TimeFromUnixTimestampDecimal(wsOrder.Timestamp) } - var p currency.Pair - var a asset.Item - p, a, err = c.GetRequestFormattedPairAndAssetType(wsOrder.ProductID) - if err != nil { - return err - } - c.Websocket.DataHandler <- &order.Detail{ - HiddenOrder: wsOrder.Private, - Price: wsOrder.Price, - Amount: wsOrder.Size, - TriggerPrice: wsOrder.StopPrice, - ExecutedAmount: wsOrder.Size - wsOrder.RemainingSize, - RemainingAmount: wsOrder.RemainingSize, - Fee: wsOrder.TakerFeeRate, - Exchange: c.Name, - ID: wsOrder.OrderID, - AccountID: wsOrder.ProfileID, - ClientID: c.API.Credentials.ClientID, - Type: oType, - Side: oSide, - Status: oStatus, - AssetType: a, - Date: ts, - Pair: p, + if wsOrder.UserID != "" { + var p currency.Pair + var a asset.Item + p, a, err = c.GetRequestFormattedPairAndAssetType(wsOrder.ProductID) + if err != nil { + return err + } + c.Websocket.DataHandler <- &order.Detail{ + HiddenOrder: wsOrder.Private, + Price: wsOrder.Price, + Amount: wsOrder.Size, + TriggerPrice: wsOrder.StopPrice, + ExecutedAmount: wsOrder.Size - wsOrder.RemainingSize, + RemainingAmount: wsOrder.RemainingSize, + Fee: wsOrder.TakerFeeRate, + Exchange: c.Name, + ID: wsOrder.OrderID, + AccountID: wsOrder.ProfileID, + ClientID: c.API.Credentials.ClientID, + Type: oType, + Side: oSide, + Status: oStatus, + AssetType: a, + Date: ts, + Pair: p, + } } case "match": var wsOrder wsOrderReceived @@ -214,19 +212,44 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { Err: err, } } - c.Websocket.DataHandler <- &order.Detail{ - ID: wsOrder.OrderID, - Trades: []order.TradeHistory{ - { - Price: wsOrder.Price, - Amount: wsOrder.Size, - Exchange: c.Name, - TID: strconv.FormatInt(wsOrder.TradeID, 10), - Side: oSide, - Timestamp: wsOrder.Time, - IsMaker: wsOrder.TakerUserID == "", + var p currency.Pair + var a asset.Item + p, a, err = c.GetRequestFormattedPairAndAssetType(wsOrder.ProductID) + if err != nil { + return err + } + + if wsOrder.UserID != "" { + c.Websocket.DataHandler <- &order.Detail{ + ID: wsOrder.OrderID, + Pair: p, + AssetType: a, + Trades: []order.TradeHistory{ + { + Price: wsOrder.Price, + Amount: wsOrder.Size, + Exchange: c.Name, + TID: strconv.FormatInt(wsOrder.TradeID, 10), + Side: oSide, + Timestamp: wsOrder.Time, + IsMaker: wsOrder.TakerUserID == "", + }, }, - }, + } + } else { + if !c.IsSaveTradeDataEnabled() { + return nil + } + return trade.AddTradesToBuffer(c.Name, trade.Data{ + Timestamp: wsOrder.Time, + Exchange: c.Name, + CurrencyPair: p, + AssetType: a, + Price: wsOrder.Price, + Amount: wsOrder.Size, + Side: oSide, + TID: strconv.FormatInt(wsOrder.TradeID, 10), + }) } default: c.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: c.Name + stream.UnhandledMessage + string(respRaw)} @@ -342,7 +365,7 @@ func (c *CoinbasePro) ProcessUpdate(update WebsocketL2Update) error { // GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions() func (c *CoinbasePro) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) { - var channels = []string{"heartbeat", "level2", "ticker", "user"} + var channels = []string{"heartbeat", "level2", "ticker", "user", "matches"} enabledCurrencies, err := c.GetEnabledPairs(asset.Spot) if err != nil { return nil, err diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index 69c18606..7ef7075d 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -3,6 +3,7 @@ package coinbasepro import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -436,9 +438,49 @@ func (c *CoinbasePro) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (c *CoinbasePro) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (c *CoinbasePro) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = c.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData []Trade + tradeData, err = c.GetTrades(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: c.Name, + TID: strconv.FormatInt(tradeData[i].TradeID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Size, + Timestamp: tradeData[i].Time, + }) + } + + err = c.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (c *CoinbasePro) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/coinbene/coinbene.go b/exchanges/coinbene/coinbene.go index 9080d838..b55f0792 100644 --- a/exchanges/coinbene/coinbene.go +++ b/exchanges/coinbene/coinbene.go @@ -169,13 +169,14 @@ func (c *Coinbene) GetTickers() ([]TickerData, error) { } // GetTrades gets recent trades from the exchange -func (c *Coinbene) GetTrades(symbol string) (Trades, error) { +func (c *Coinbene) GetTrades(symbol string, limit int64) (Trades, error) { resp := struct { Data [][]string `json:"data"` }{} params := url.Values{} params.Set("symbol", symbol) + params.Set("limit", strconv.FormatInt(limit, 10)) path := common.EncodeURLValues(c.API.Endpoints.URL+coinbeneAPIVersion+coinbeneGetTrades, params) err := c.SendHTTPRequest(path, spotMarketTrades, &resp) if err != nil { diff --git a/exchanges/coinbene/coinbene_test.go b/exchanges/coinbene/coinbene_test.go index cdae5bae..e85d46ac 100644 --- a/exchanges/coinbene/coinbene_test.go +++ b/exchanges/coinbene/coinbene_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -86,7 +87,7 @@ func TestGetTicker(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := c.GetTrades(spotTestPair) + _, err := c.GetTrades(spotTestPair, 100) if err != nil { t.Error(err) } @@ -498,63 +499,13 @@ func TestWsLogin(t *testing.T) { } func TestWsOrderbook(t *testing.T) { - pressXToJSON := []byte(`{ - "topic": "orderBook.BTCUSDT", - "action": "insert", - "data": [{ - "asks": [ - ["5621.7", "58", "2"], - ["5621.8", "125", "5"], - ["5621.9", "100", "9"], - ["5622", "84", "20"], - ["5623.5", "90", "12"], - ["5624.2", "1540", "15"], - ["5625.1", "300", "20"], - ["5625.9", "350", "1"], - ["5629.3", "200", "1"], - ["5650", "1000", "8"] - ], - "bids": [ - ["5621.3", "287","8"], - ["5621.2", "41","1"], - ["5621.1", "2","1"], - ["5621", "26","2"], - ["5620.8", "194","2"], - ["5620", "2", "1"], - ["5618.8", "204","2"], - ["5618.4", "30", "9"], - ["5617.2", "2","1"], - ["5609.9", "100", "12"] - ], - "version":1, - "timestamp": "2019-07-04T02:21:08Z" - }] - }`) + pressXToJSON := []byte(`{"topic":"spot/orderBook.BTCUSDT","action":"insert","data":[{"bids":[["0.00000015","174215.91"],["0.00000012","600000.00"],["0.00000010","10000.00"],["0.00000006","33333.00"],["0.00000004","50000.00"],["0.00000003","2000000.00"],["0.00000002","100000.00"],["0.00000001","1100000.00"]],"asks":[["0.00000262","5152.79"],["0.00000263","44626.00"],["0.00000340","2649.85"],["0.00000398","20056.93"],["0.00000400","1420385.54"],["0.00000790","8594.85"],["0.00000988","42380.97"],["0.00000997","43850.97"],["0.00001398","10541.59"],["0.00001400","3409.29"],["0.00002636","52.11"],["0.00002810","2543.66"],["0.00003200","1018.36"],["0.00004999","19.81"],["0.00005000","400.00"],["0.00005898","4060.56"],["0.00006498","3302.60"],["0.00006668","4060.56"],["0.00008000","400.00"]],"version":4915,"timestamp":1598529668288}]}`) err := c.wsHandleData(pressXToJSON) if err != nil { t.Error(err) } - pressXToJSON = []byte(`{ - "topic": "orderBook.BTCUSDT", - "action": "update", - "data": [{ - "asks": [ - ["5621.7", "50", "2"], - ["5621.8", "0", "0"], - ["5621.9", "30", "5"] - ], - "bids": [ - ["5621.3", "10","1"], - ["5621.2", "20","1"], - ["5621.1", "80","5"], - ["5621", "0","0"], - ["5620.8", "10","1"] - ], - "version":2, - "timestamp": "2019-07-04T02:21:09Z" - }] - }`) + pressXToJSON = []byte(`{"topic":"spot/orderBook.BTCUSDT","action":"update","data":[{"bids":[["2.983","8696"]],"asks":[["3.113","0"]],"version":34600866,"timestamp":1598587478738}]}`) err = c.wsHandleData(pressXToJSON) if err != nil { t.Error(err) @@ -562,17 +513,7 @@ func TestWsOrderbook(t *testing.T) { } func TestWsTrade(t *testing.T) { - pressXToJSON := []byte(`{ - "topic": "tradeList.BTCUSDT", - "data": [ - [ - "8600.0000", - "s", - "100", - "2019-05-21T08:25:22.735Z" - ] - ] - }`) + pressXToJSON := []byte(`{"data":[["0.00000050","s","37.00",1598500505000],["0.00000060","s","10.00",1598499782000],["0.00000066","s","1.00",1598499782000],["0.00000067","s","1.00",1598499782000],["0.00000068","s","1.00",1598499745000],["0.00000080","b","1.00",1598262728000],["0.00000089","b","5592.81",1597738441000],["0.00000072","b","1.00",1597693134000],["0.00000069","s","21739.13",1597378140000],["0.00000069","s","1.00",1597378140000],["0.00000074","b","1.00",1597354497000],["0.00000079","b","1.00",1597325675000],["0.00000082","b","1.00",1597162162000],["0.00000089","b","1.00",1597084892000],["0.00000073","b","109404.43",1597015827000],["0.00000070","b","1067.00",1597015827000],["0.00000070","b","1.00",1594732841000],["0.00000070","b","10.00",1592178569000],["0.00000065","b","194.76",1592178545000],["0.00000064","b","2.37",1592105641000],["0.00000064","b","3.00",1592087828000],["0.00000045","b","5.00",1592087828000],["0.00000045","b","5.00",1592004274000],["0.00000030","s","100.00",1591931268000],["0.00000020","b","138.12",1591928623000],["0.00000020","b","55027.66",1591928623000],["0.00000020","b","59880.11",1591572812000],["0.00000021","s","138.12",1590413750000],["0.00000021","s","5.37",1590413750000],["0.00000056","s","1.00",1589567228000],["0.00000065","b","1.00",1589567217000],["0.00000060","b","84890.64",1589407481000],["0.00000060","b","17.13",1589407433000],["0.00000060","b","9148.70",1589389270000],["0.00000059","b","9010.00",1589389159000],["0.00000055","b","3876.00",1589389098000],["0.00000055","b","30000.00",1588899981000],["0.00000055","b","5724.00",1588891192000],["0.00000050","b","400.00",1588891192000],["0.00000048","b","26874.64",1588891129000],["0.00000048","b","2.00",1588891129000],["0.00000049","b","7547.75",1585279296000],["0.00000049","b","12180.30",1584932828000],["0.00000049","b","8256.95",1584932828000],["0.00000053","b","500.42",1583351500000],["0.00000053","b","500.00",1583351484000],["0.00000053","b","400.00",1583351470000],["0.00000053","b","394.62",1583351455000],["0.00000053","b","1.99",1583343633000],["0.00000018","s","250.00",1583338813000]],"topic":"spot/tradeList.BTCUSDT","action":"insert"}`) err := c.wsHandleData(pressXToJSON) if err != nil { t.Error(err) @@ -580,24 +521,7 @@ func TestWsTrade(t *testing.T) { } func TestWsTicker(t *testing.T) { - pressXToJSON := []byte(`{ - "topic": "ticker.BTCUSDT", - "data": [ - { - "symbol": "BTCUSDT", - "lastPrice": "8548.0", - "markPrice": "8548.0", - "bestAskPrice": "8601.0", - "bestBidPrice": "8600.0", - "bestAskVolume": "1222", - "bestBidVolume": "56505", - "high24h": "8600.0000", - "low24h": "242.4500", - "volume24h": "4994", - "timestamp": "2019-05-06T06:45:56.716Z" - } - ] - }`) + pressXToJSON := []byte(`{"topic": "spot/ticker.BTCUSDT","action":"insert","data": [{"symbol":"BTCUSDT","lastPrice":"23.3746","bestAskPrice":"23.3885","bestBidPrice":"23.3603","high24h":"23.5773","open24h":"22.1961","openPrice":"22.5546","low24h":"21.8077","volume24h":"3784807.9709","timestamp":1598587472634}]}`) err := c.wsHandleData(pressXToJSON) if err != nil { t.Error(err) @@ -605,23 +529,7 @@ func TestWsTicker(t *testing.T) { } func TestWsKLine(t *testing.T) { - pressXToJSON := []byte(`{ - "topic": "kline.BTCUSDT", - "data": [ - [ - "BTCUSDT", - 1557428280, - "5794", - "5794", - "5794", - "5794", - "0", - "0", - "0", - "0" - ] - ] - }`) + pressXToJSON := []byte(`{"topic": "spot/kline.BTCUSDT.1h","action":"insert","data": [{"t":1594990800,"o":1.1e-07,"h":1.1e-07,"l":1.1e-07,"c":1.1e-07,"v":0}]}`) err := c.wsHandleData(pressXToJSON) if err != nil { t.Error(err) @@ -630,7 +538,7 @@ func TestWsKLine(t *testing.T) { func TestWsUserAccount(t *testing.T) { pressXToJSON := []byte(`{ - "topic": "user.account", + "topic": "btc/user.account", "data": [{ "asset": "BTC", "availableBalance": "20.3859", @@ -780,3 +688,75 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestInferAssetFromTopic(t *testing.T) { + a := inferAssetFromTopic("spot/orderBook.BSVBTC") + if a != asset.Spot { + t.Error("expected spot") + } + a = inferAssetFromTopic("btc/orderBook.BSVBTC") + if a != asset.PerpetualSwap { + t.Error("expected PerpetualSwap") + } + a = inferAssetFromTopic("usdt/orderBook.BSVBTC") + if a != asset.PerpetualSwap { + t.Error("expected PerpetualSwap") + } + a = inferAssetFromTopic("orderBook.BSVBTC") + if a != asset.PerpetualSwap { + t.Error("expected PerpetualSwap") + } + a = inferAssetFromTopic("") + if a != asset.PerpetualSwap { + t.Error("expected PerpetualSwap") + } +} + +func TestGetCurrencyFromWsTopic(t *testing.T) { + p, err := c.getCurrencyFromWsTopic(asset.Spot, "spot/orderbook.BTCUSDT") + if err != nil { + t.Error(err) + } + if p.Base.String() != "BTC" && p.Quote.String() != "USDT" { + t.Errorf("unexpected currency, wanted BTCUSD, received %v", p.String()) + } + + _, err = c.getCurrencyFromWsTopic(asset.Spot, "fake") + if err != nil && err.Error() != "no currency found in topic fake" { + t.Error(err) + } + + _, err = c.getCurrencyFromWsTopic(asset.Spot, "hello.moto") + if err != nil && err.Error() != "currency moto not found in supplied pairs" { + t.Error(err) + } + + _, err = c.getCurrencyFromWsTopic(asset.Spot, "spot/kline.GOM2USDT.1h") + if err != nil && err.Error() != "currency moto not found in enabled pairs" { + t.Error(err) + } +} + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(spotTestPair) + if err != nil { + t.Fatal(err) + } + _, err = c.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(spotTestPair) + if err != nil { + t.Fatal(err) + } + _, err = c.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/coinbene/coinbene_types.go b/exchanges/coinbene/coinbene_types.go index 2fd684de..dfa8c72e 100644 --- a/exchanges/coinbene/coinbene_types.go +++ b/exchanges/coinbene/coinbene_types.go @@ -123,17 +123,17 @@ type WsSub struct { // WsTickerData stores websocket ticker data type WsTickerData struct { - Symbol string `json:"symbol"` - LastPrice float64 `json:"lastPrice,string"` - MarkPrice float64 `json:"markPrice,string"` - BestAskPrice float64 `json:"bestAskPrice,string"` - BestBidPrice float64 `json:"bestBidPrice,string"` - BestAskVolume float64 `json:"bestAskVolume,string"` - BestBidVolume float64 `json:"bestBidVolume,string"` - High24h float64 `json:"high24h,string"` - Low24h float64 `json:"low24h,string"` - Volume24h float64 `json:"volume24h,string"` - Timestamp time.Time `json:"timestamp"` + Symbol string `json:"symbol"` + LastPrice float64 `json:"lastPrice,string"` + MarkPrice float64 `json:"markPrice,string"` + BestAskPrice float64 `json:"bestAskPrice,string"` + BestBidPrice float64 `json:"bestBidPrice,string"` + BestAskVolume float64 `json:"bestAskVolume,string"` + BestBidVolume float64 `json:"bestBidVolume,string"` + High24h float64 `json:"high24h,string"` + Low24h float64 `json:"low24h,string"` + Volume24h float64 `json:"volume24h,string"` + Timestamp int64 `json:"timestamp"` } // WsTicker stores websocket ticker @@ -144,14 +144,38 @@ type WsTicker struct { // WsTradeList stores websocket tradelist data type WsTradeList struct { - Topic string `json:"topic"` - Data [][]string `json:"data"` + Topic string `json:"topic"` + Data [][4]interface{} `json:"data"` +} + +// WsTradeData stores trade data for websocket +type WsTradeData struct { + BestAskPrice float64 `json:"bestAskPrice,string"` + BestBidPrice float64 `json:"bestBidPrice,string"` + High24h float64 `json:"high24h,string"` + LastPrice float64 `json:"lastPrice,string"` + Low24h float64 `json:"low24h,string"` + Open24h float64 `json:"open24h,string"` + OpenPrice float64 `json:"openPrice,string"` + Symbol string `json:"symbol"` + Timestamp int64 `json:"timestamp"` + Volume24h float64 `json:"volume24h,string"` } // WsKline stores websocket kline data type WsKline struct { - Topic string `json:"topic"` - Data [][]interface{} `json:"data"` + Topic string `json:"topic"` + Data []WsKLineData `json:"data"` +} + +// WsKLineData holds OHLCV data +type WsKLineData struct { + Open float64 `json:"o"` + High float64 `json:"h"` + Low float64 `json:"l"` + Close float64 `json:"c"` + Volume float64 `json:"v"` + Timestamp int64 `json:"t"` } // WsUserData stores websocket user data @@ -191,6 +215,18 @@ type WsPosition struct { Data []WsPositionData `json:"data"` } +// WsOrderbookData stores ws orderbook data +type WsOrderbookData struct { + Topic string `json:"topic"` + Action string `json:"action"` + Data []struct { + Bids [][]string `json:"bids"` + Asks [][]string `json:"asks"` + Version int64 `json:"version"` + Timestamp int64 `json:"timestamp"` + } `json:"data"` +} + // WsOrderData stores websocket user order data type WsOrderData struct { OrderID string `json:"orderId"` diff --git a/exchanges/coinbene/coinbene_websocket.go b/exchanges/coinbene/coinbene_websocket.go index bc364ce2..b2557fac 100644 --- a/exchanges/coinbene/coinbene_websocket.go +++ b/exchanges/coinbene/coinbene_websocket.go @@ -19,12 +19,15 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" ) const ( - wsContractURL = "wss://ws-contract.coinbene.vip/openapi/ws" - event = "event" - topic = "topic" + wsContractURL = "wss://ws.coinbene.com/stream/ws" + event = "event" + topic = "topic" + swapChannelPrefix = "btc/" + spotChannelPrefix = "spot/" ) // WsConnect connects to websocket @@ -55,22 +58,36 @@ func (c *Coinbene) WsConnect() error { // GenerateDefaultSubscriptions generates stuff func (c *Coinbene) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) { - var channels = []string{"orderBook.%s.100", "tradeList.%s", "ticker.%s", "kline.%s"} + var channels = []string{"orderBook.%s.100", "tradeList.%s", "ticker.%s", "kline.%s.1h"} var subscriptions []stream.ChannelSubscription - pairs, err := c.GetEnabledPairs(asset.PerpetualSwap) + perpetualPairs, err := c.GetEnabledPairs(asset.PerpetualSwap) + if err != nil { + return nil, err + } + var spotPairs currency.Pairs + spotPairs, err = c.GetEnabledPairs(asset.Spot) if err != nil { return nil, err } for x := range channels { - for y := range pairs { - pairs[y].Delimiter = "" + for y := range perpetualPairs { + perpetualPairs[y].Delimiter = "" subscriptions = append(subscriptions, stream.ChannelSubscription{ - Channel: fmt.Sprintf(channels[x], pairs[y]), - Currency: pairs[y], + Channel: swapChannelPrefix + fmt.Sprintf(channels[x], perpetualPairs[y]), + Currency: perpetualPairs[y], Asset: asset.PerpetualSwap, }) } + for z := range spotPairs { + spotPairs[z].Delimiter = "" + subscriptions = append(subscriptions, stream.ChannelSubscription{ + Channel: spotChannelPrefix + fmt.Sprintf(channels[x], spotPairs[z]), + Currency: spotPairs[z], + Asset: asset.Spot, + }) + } } + return subscriptions, nil } @@ -102,6 +119,13 @@ func (c *Coinbene) wsReadData() { } } +func inferAssetFromTopic(topic string) asset.Item { + if strings.Contains(topic, "spot/") { + return asset.Spot + } + return asset.PerpetualSwap +} + func (c *Coinbene) wsHandleData(respRaw []byte) error { if string(respRaw) == stream.Ping { err := c.Websocket.Conn.SendRawMessage(websocket.TextMessage, []byte(stream.Pong)) @@ -135,6 +159,8 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { c.Websocket.SetCanUseAuthenticatedEndpoints(false) return fmt.Errorf("message: %s. code: %v", result["message"], result["code"]) } + assetType := inferAssetFromTopic(result[topic].(string)) + var newPair currency.Pair switch { case strings.Contains(result[topic].(string), "ticker"): var wsTicker WsTicker @@ -142,27 +168,12 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { if err != nil { return err } - - var format currency.PairFormat - format, err = c.GetPairFormat(asset.PerpetualSwap, true) - if err != nil { - return err - } - - var pairs currency.Pairs - pairs, err = c.GetEnabledPairs(asset.PerpetualSwap) + newPair, err = c.getCurrencyFromWsTopic(assetType, wsTicker.Topic) if err != nil { return err } for x := range wsTicker.Data { - var p currency.Pair - p, err = currency.NewPairFromFormattedPairs(wsTicker.Data[x].Symbol, - pairs, - format) - if err != nil { - return err - } c.Websocket.DataHandler <- &ticker.Price{ Volume: wsTicker.Data[x].Volume24h, Last: wsTicker.Data[x].LastPrice, @@ -170,100 +181,66 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { Low: wsTicker.Data[x].Low24h, Bid: wsTicker.Data[x].BestBidPrice, Ask: wsTicker.Data[x].BestAskPrice, - Pair: p, + Pair: newPair, ExchangeName: c.Name, - AssetType: asset.PerpetualSwap, - LastUpdated: wsTicker.Data[x].Timestamp, + AssetType: assetType, + LastUpdated: time.Unix(wsTicker.Data[x].Timestamp, 0), } } case strings.Contains(result[topic].(string), "tradeList"): + if !c.IsSaveTradeDataEnabled() { + return nil + } var tradeList WsTradeList err = json.Unmarshal(respRaw, &tradeList) if err != nil { return err } - var t time.Time - var price, amount float64 - t, err = time.Parse(time.RFC3339, tradeList.Data[0][3]) - if err != nil { - return err - } - price, err = strconv.ParseFloat(tradeList.Data[0][0], 64) - if err != nil { - return err - } - amount, err = strconv.ParseFloat(tradeList.Data[0][2], 64) - if err != nil { - return err - } - p := strings.Replace(tradeList.Topic, "tradeList.", "", 1) - var tSide = order.Buy - if tradeList.Data[0][1] == "s" { - tSide = order.Sell - } + var trades []trade.Data + for i := range tradeList.Data { + var price, amount float64 + t := time.Unix(int64(tradeList.Data[i][3].(float64))/1000, 0) + price, err = strconv.ParseFloat(tradeList.Data[i][0].(string), 64) + if err != nil { + return err + } + amount, err = strconv.ParseFloat(tradeList.Data[i][2].(string), 64) + if err != nil { + return err + } - var format currency.PairFormat - format, err = c.GetPairFormat(asset.PerpetualSwap, true) - if err != nil { - return err - } + var tSide = order.Buy + if tradeList.Data[i][1] == "s" { + tSide = order.Sell + } - var pairs currency.Pairs - pairs, err = c.GetEnabledPairs(asset.PerpetualSwap) - if err != nil { - return err - } + newPair, err = c.getCurrencyFromWsTopic(assetType, tradeList.Topic) + if err != nil { + return err + } - var newP currency.Pair - newP, err = currency.NewPairFromFormattedPairs(p, pairs, format) - if err != nil { - return err - } - - c.Websocket.DataHandler <- stream.TradeData{ - CurrencyPair: newP, - Timestamp: t, - Price: price, - Amount: amount, - Exchange: c.Name, - AssetType: asset.PerpetualSwap, - Side: tSide, + trades = append(trades, trade.Data{ + Timestamp: t, + Exchange: c.Name, + CurrencyPair: newPair, + AssetType: assetType, + Price: price, + Amount: amount, + Side: tSide, + }) } + return trade.AddTradesToBuffer(c.Name, trades...) case strings.Contains(result[topic].(string), "orderBook"): - orderBook := struct { - Topic string `json:"topic"` - Action string `json:"action"` - Data []struct { - Bids [][]string `json:"bids"` - Asks [][]string `json:"asks"` - Version int64 `json:"version"` - Timestamp time.Time `json:"timestamp"` - } `json:"data"` - }{} + var orderBook WsOrderbookData err = json.Unmarshal(respRaw, &orderBook) if err != nil { return err } - p := strings.Replace(orderBook.Topic, "orderBook.", "", 1) - var format currency.PairFormat - format, err = c.GetPairFormat(asset.PerpetualSwap, true) + newPair, err = c.getCurrencyFromWsTopic(assetType, orderBook.Topic) if err != nil { return err } - - var pairs currency.Pairs - pairs, err = c.GetEnabledPairs(asset.PerpetualSwap) - if err != nil { - return err - } - - var newP currency.Pair - newP, err = currency.NewPairFromFormattedPairs(p, pairs, format) - if err != nil { - return err - } - var amount, price float64 var asks, bids []orderbook.Item for i := range orderBook.Data[0].Asks { @@ -298,10 +275,10 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { var newOB orderbook.Base newOB.Asks = asks newOB.Bids = bids - newOB.AssetType = asset.PerpetualSwap - newOB.Pair = newP + newOB.AssetType = assetType + newOB.Pair = newPair newOB.ExchangeName = c.Name - newOB.LastUpdated = orderBook.Data[0].Timestamp + newOB.LastUpdated = time.Unix(orderBook.Data[0].Timestamp, 0) err = c.Websocket.Orderbook.LoadSnapshot(&newOB) if err != nil { return err @@ -310,10 +287,10 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { newOB := buffer.Update{ Asks: asks, Bids: bids, - Asset: asset.PerpetualSwap, - Pair: newP, + Asset: assetType, + Pair: newPair, UpdateID: orderBook.Data[0].Version, - UpdateTime: orderBook.Data[0].Timestamp, + UpdateTime: time.Unix(orderBook.Data[0].Timestamp, 0), } err = c.Websocket.Orderbook.Update(&newOB) if err != nil { @@ -321,54 +298,28 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { } } case strings.Contains(result[topic].(string), "kline"): - var kline WsKline - var tempFloat float64 - var tempKline []float64 - err = json.Unmarshal(respRaw, &kline) + var candleData WsKline + err = json.Unmarshal(respRaw, &candleData) if err != nil { return err } - for x := 2; x < len(kline.Data[0]); x++ { - tempFloat, err = strconv.ParseFloat(kline.Data[0][x].(string), 64) - if err != nil { - return err + newPair, err = c.getCurrencyFromWsTopic(assetType, candleData.Topic) + if err != nil { + return err + } + + for i := range candleData.Data { + c.Websocket.DataHandler <- stream.KlineData{ + Pair: newPair, + AssetType: assetType, + Exchange: c.Name, + OpenPrice: candleData.Data[i].Open, + HighPrice: candleData.Data[i].High, + LowPrice: candleData.Data[i].Low, + ClosePrice: candleData.Data[i].Close, + Volume: candleData.Data[i].Volume, + Timestamp: time.Unix(candleData.Data[i].Timestamp, 0), } - tempKline = append(tempKline, tempFloat) - } - - var format currency.PairFormat - format, err = c.GetPairFormat(asset.PerpetualSwap, true) - if err != nil { - return err - } - - var pairs currency.Pairs - pairs, err = c.GetEnabledPairs(asset.PerpetualSwap) - if err != nil { - return err - } - - var newP currency.Pair - newP, err = currency.NewPairFromFormattedPairs(kline.Data[0][0].(string), - pairs, - format) - if err != nil { - return err - } - - if tempKline == nil && len(tempKline) < 5 { - return errors.New(c.Name + " - received bad data ") - } - c.Websocket.DataHandler <- stream.KlineData{ - Timestamp: time.Unix(int64(kline.Data[0][1].(float64)), 0), - Pair: newP, - AssetType: asset.PerpetualSwap, - Exchange: c.Name, - OpenPrice: tempKline[0], - ClosePrice: tempKline[1], - HighPrice: tempKline[2], - LowPrice: tempKline[3], - Volume: tempKline[4], } case strings.Contains(result[topic].(string), "user.account"): var userInfo WsUserInfo @@ -391,12 +342,12 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { return err } - format, err := c.GetPairFormat(asset.PerpetualSwap, true) + format, err := c.GetPairFormat(assetType, true) if err != nil { return err } - pairs, err := c.GetEnabledPairs(asset.PerpetualSwap) + pairs, err := c.GetEnabledPairs(assetType) if err != nil { return err } @@ -419,7 +370,7 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { } } - newP, err := currency.NewPairFromFormattedPairs(orders.Data[i].Symbol, + newPair, err = currency.NewPairFromFormattedPairs(orders.Data[i].Symbol, pairs, format) if err != nil { @@ -436,10 +387,10 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { ID: orders.Data[i].OrderID, Type: oType, Status: oStatus, - AssetType: asset.PerpetualSwap, + AssetType: assetType, Date: orders.Data[i].OrderTime, Leverage: strconv.FormatInt(orders.Data[i].Leverage, 10), - Pair: newP, + Pair: newPair, } } default: @@ -451,11 +402,48 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error { return nil } +func (c *Coinbene) getCurrencyFromWsTopic(assetType asset.Item, channelTopic string) (cp currency.Pair, err error) { + var format currency.PairFormat + format, err = c.GetPairFormat(assetType, true) + if err != nil { + return cp, err + } + + var pairs currency.Pairs + pairs, err = c.GetEnabledPairs(assetType) + if err != nil { + return cp, err + } + // channel topics are formatted as "spot/orderbook.BTCUSDT" + channelSplit := strings.Split(channelTopic, ".") + if len(channelSplit) == 1 { + return currency.Pair{}, errors.New("no currency found in topic " + channelTopic) + } + cp, err = currency.MatchPairsWithNoDelimiter(channelSplit[1], pairs, format) + if err != nil { + return cp, err + } + if !pairs.Contains(cp, true) { + return cp, fmt.Errorf("currency %s not found in enabled pairs", cp.String()) + } + return cp, nil +} + // Subscribe sends a websocket message to receive data from the channel func (c *Coinbene) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error { var sub WsSub sub.Operation = "subscribe" + // enabling all currencies can lead to a message too large being sent + // and no subscriptions being made + chanLimit := 10 for i := range channelsToSubscribe { + if len(sub.Arguments) > chanLimit { + err := c.Websocket.Conn.SendJSONMessage(sub) + if err != nil { + return err + } + sub.Arguments = []string{} + } sub.Arguments = append(sub.Arguments, channelsToSubscribe[i].Channel) } err := c.Websocket.Conn.SendJSONMessage(sub) @@ -470,7 +458,17 @@ func (c *Coinbene) Subscribe(channelsToSubscribe []stream.ChannelSubscription) e func (c *Coinbene) Unsubscribe(channelToUnsubscribe []stream.ChannelSubscription) error { var unsub WsSub unsub.Operation = "unsubscribe" + // enabling all currencies can lead to a message too large being sent + // and no unsubscribes being made + chanLimit := 10 for i := range channelToUnsubscribe { + if len(unsub.Arguments) > chanLimit { + err := c.Websocket.Conn.SendJSONMessage(unsub) + if err != nil { + return err + } + unsub.Arguments = []string{} + } unsub.Arguments = append(unsub.Arguments, channelToUnsubscribe[i].Channel) } err := c.Websocket.Conn.SendJSONMessage(unsub) diff --git a/exchanges/coinbene/coinbene_wrapper.go b/exchanges/coinbene/coinbene_wrapper.go index a5845ba7..39b98824 100644 --- a/exchanges/coinbene/coinbene_wrapper.go +++ b/exchanges/coinbene/coinbene_wrapper.go @@ -3,6 +3,7 @@ package coinbene import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -505,8 +507,46 @@ func (c *Coinbene) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (c *Coinbene) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { +// GetRecentTrades returns the most recent trades for a currency and asset +func (c *Coinbene) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = c.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData Trades + tradeData, err = c.GetTrades(p.String(), 100) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + side := order.Buy + if tradeData[i].Direction == "sell" { + side = order.Sell + } + resp = append(resp, trade.Data{ + Exchange: c.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Volume, + Timestamp: tradeData[i].TradeTime, + }) + } + + err = c.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (c *Coinbene) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index 8ac22eca..7d456246 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -98,7 +98,7 @@ func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int64) (Orderbook, e } // GetTrades returns trade information -func (c *COINUT) GetTrades(instrumentID int) (Trades, error) { +func (c *COINUT) GetTrades(instrumentID int64) (Trades, error) { var result Trades params := make(map[string]interface{}) params["inst_id"] = instrumentID diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index 6bf33d31..f944aeb3 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -5,6 +5,7 @@ import ( "net/http" "os" "testing" + "time" "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common" @@ -738,6 +739,7 @@ func TestWsGetInstruments(t *testing.T) { func TestWsTrades(t *testing.T) { pressXToJSON := []byte(`{ + "inst_id": 1, "nonce": 450319, "reply": "inst_trade", "status": [ @@ -1121,3 +1123,27 @@ func TestStringToStatus(t *testing.T) { } } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("LTC-USDT") + if err != nil { + t.Fatal(err) + } + _, err = c.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = c.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/coinut/coinut_types.go b/exchanges/coinut/coinut_types.go index a4a6d148..0edc40d9 100644 --- a/exchanges/coinut/coinut_types.go +++ b/exchanges/coinut/coinut_types.go @@ -68,9 +68,9 @@ type Orderbook struct { // TradeBase is a sub-type holding information on trades type TradeBase struct { Price float64 `json:"price,string"` - Quantity float64 `json:"quantity,string"` + Quantity float64 `json:"qty,string"` Side string `json:"side"` - Timestamp float64 `json:"timestamp"` + Timestamp int64 `json:"timestamp"` TransactionID int64 `json:"trans_id"` } @@ -344,29 +344,32 @@ type WsOrderbookUpdate struct { // WsTradeSnapshot defines Market trade response from the websocket // connection type WsTradeSnapshot struct { - Nonce int64 `json:"nonce"` - Reply string `json:"reply"` - Status []interface{} `json:"status"` - Trades []WsTradeData `json:"trades"` + InstrumentID int64 `json:"inst_id"` + Nonce int64 `json:"nonce"` + Reply string `json:"reply"` + Status []interface{} `json:"status"` + Trades []WsTradeData `json:"trades"` } // WsTradeData defines market trade data type WsTradeData struct { + InstID int64 `json:"inst_id"` + TransID int64 `json:"trans_id"` Price float64 `json:"price,string"` - Volume float64 `json:"qty,string"` + Quantity float64 `json:"qty,string"` Side string `json:"side"` Timestamp int64 `json:"timestamp"` - TransID int64 `json:"trans_id"` } // WsTradeUpdate defines trade update response from the websocket connection type WsTradeUpdate struct { InstID int64 `json:"inst_id"` + TransID int64 `json:"trans_id"` Price float64 `json:"price,string"` - Reply string `json:"reply"` + Quantity float64 `json:"qty,string"` Side string `json:"side"` Timestamp int64 `json:"timestamp"` - TransID int64 `json:"trans_id"` + Reply string `json:"reply"` } // WsInstrumentList defines instrument list diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index 2aac6cc6..1b2bc94a 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -288,13 +289,52 @@ func (c *COINUT) wsHandleData(respRaw []byte) error { return err } case "inst_trade": + if !c.IsSaveTradeDataEnabled() { + return nil + } var tradeSnap WsTradeSnapshot err := json.Unmarshal(respRaw, &tradeSnap) if err != nil { return err } + var trades []trade.Data + for i := range tradeSnap.Trades { + pairs, err := c.GetEnabledPairs(asset.Spot) + if err != nil { + return err + } + currencyPair := c.instrumentMap.LookupInstrument(tradeSnap.InstrumentID) + p, err := currency.NewPairFromFormattedPairs(currencyPair, + pairs, + format) + if err != nil { + return err + } + tSide, err := order.StringToOrderSide(tradeSnap.Trades[i].Side) + if err != nil { + c.Websocket.DataHandler <- order.ClassificationError{ + Exchange: c.Name, + Err: err, + } + } + + trades = append(trades, trade.Data{ + Timestamp: time.Unix(0, tradeSnap.Trades[i].Timestamp*1000), + CurrencyPair: p, + AssetType: asset.Spot, + Exchange: c.Name, + Price: tradeSnap.Trades[i].Price, + Side: tSide, + Amount: tradeSnap.Trades[i].Quantity, + TID: strconv.FormatInt(tradeSnap.Trades[i].TransID, 10), + }) + } + return trade.AddTradesToBuffer(c.Name, trades...) case "inst_trade_update": + if !c.IsSaveTradeDataEnabled() { + return nil + } var tradeUpdate WsTradeUpdate err := json.Unmarshal(respRaw, &tradeUpdate) if err != nil { @@ -321,14 +361,16 @@ func (c *COINUT) wsHandleData(respRaw []byte) error { } } - c.Websocket.DataHandler <- stream.TradeData{ - Timestamp: time.Unix(tradeUpdate.Timestamp, 0), + return trade.AddTradesToBuffer(c.Name, trade.Data{ + Timestamp: time.Unix(0, tradeUpdate.Timestamp*1000), CurrencyPair: p, AssetType: asset.Spot, Exchange: c.Name, Price: tradeUpdate.Price, Side: tSide, - } + Amount: tradeUpdate.Quantity, + TID: strconv.FormatInt(tradeUpdate.TransID, 10), + }) case "order_filled", "order_rejected", "order_accepted": var orderContainer wsOrderContainer err := json.Unmarshal(respRaw, &orderContainer) @@ -557,7 +599,7 @@ func (c *COINUT) WsProcessOrderbookUpdate(update *WsOrderbookUpdate) error { // GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions() func (c *COINUT) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) { - var channels = []string{"inst_tick", "inst_order_book"} + var channels = []string{"inst_tick", "inst_order_book", "inst_trade"} var subscriptions []stream.ChannelSubscription enabledCurrencies, err := c.GetEnabledPairs(asset.Spot) if err != nil { diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index e4924a09..f9639f38 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math/rand" + "sort" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -498,9 +500,53 @@ func (c *COINUT) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (c *COINUT) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (c *COINUT) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = c.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + currencyID := c.instrumentMap.LookupID(p.String()) + if currencyID == 0 { + return nil, errLookupInstrumentID + } + var tradeData Trades + tradeData, err = c.GetTrades(currencyID) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData.Trades { + var side order.Side + side, err = order.StringToOrderSide(tradeData.Trades[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: c.Name, + TID: strconv.FormatInt(tradeData.Trades[i].TransactionID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData.Trades[i].Price, + Amount: tradeData.Trades[i].Quantity, + Timestamp: time.Unix(0, tradeData.Trades[i].Timestamp*int64(time.Microsecond)), + }) + } + + err = c.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (c *COINUT) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 7fb9be1e..db921159 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -19,6 +19,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/banking" ) @@ -154,6 +155,10 @@ func (e *Base) SetFeatureDefaults() { e.Config.Features.Supports.Websocket = e.Features.Supports.Websocket } + if e.IsSaveTradeDataEnabled() != e.Config.Features.Enabled.SaveTradeData { + e.SetSaveTradeDataStatus(e.Config.Features.Enabled.SaveTradeData) + } + e.Features.Enabled.AutoPairUpdates = e.Config.Features.Enabled.AutoPairUpdates } } @@ -994,6 +999,8 @@ func (e *Base) SetGlobalPairsManager(request, config *currency.PairFormat, asset e.Name) } e.CurrencyPairs.Pairs[assets[i]] = new(currency.PairStore) + e.CurrencyPairs.Pairs[assets[i]].ConfigFormat = config + e.CurrencyPairs.Pairs[assets[i]].RequestFormat = request } return nil @@ -1097,3 +1104,34 @@ func (e *Base) ValidateKline(pair currency.Pair, a asset.Item, interval kline.In return nil } + +// AddTradesToBuffer is a helper function that will only +// add trades to the buffer if it is allowed +func (e *Base) AddTradesToBuffer(trades ...trade.Data) error { + if !e.IsSaveTradeDataEnabled() { + return nil + } + + return trade.AddTradesToBuffer(e.Name, trades...) +} + +// IsSaveTradeDataEnabled checks the state of +// SaveTradeData in a concurrent-friendly manner +func (e *Base) IsSaveTradeDataEnabled() bool { + e.settingsMutex.RLock() + isEnabled := e.Features.Enabled.SaveTradeData + e.settingsMutex.RUnlock() + return isEnabled +} + +// SetSaveTradeDataStatus locks and sets the status of +// the config and the exchange's setting for SaveTradeData +func (e *Base) SetSaveTradeDataStatus(enabled bool) { + e.settingsMutex.Lock() + defer e.settingsMutex.Unlock() + e.Features.Enabled.SaveTradeData = enabled + e.Config.Features.Enabled.SaveTradeData = enabled + if e.Verbose { + log.Debugf(log.Trade, "Set %v 'SaveTradeData' to %v", e.Name, enabled) + } +} diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 48ac54b1..5e33782c 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -29,7 +29,9 @@ const ( func TestMain(m *testing.M) { c := log.GenDefaultSettings() + log.RWM.Lock() log.GlobalLogConfig = &c + log.RWM.Unlock() log.SetupGlobalLogger() os.Exit(m.Run()) } @@ -2052,3 +2054,56 @@ func TestFormatExchangeKlineInterval(t *testing.T) { t.Fatal("unexpected value") } } + +func TestSetSaveTradeDataStatus(t *testing.T) { + b := Base{ + Features: Features{ + Enabled: FeaturesEnabled{ + SaveTradeData: false, + }, + }, + Config: &config.ExchangeConfig{ + Features: &config.FeaturesConfig{ + Enabled: config.FeaturesEnabledConfig{}, + }, + }, + } + + if b.IsSaveTradeDataEnabled() { + t.Errorf("expected false") + } + b.SetSaveTradeDataStatus(true) + if !b.IsSaveTradeDataEnabled() { + t.Errorf("expected true") + } + b.SetSaveTradeDataStatus(false) + if b.IsSaveTradeDataEnabled() { + t.Errorf("expected false") + } + // data race this + go b.SetSaveTradeDataStatus(false) + go b.SetSaveTradeDataStatus(true) +} + +func TestAddTradesToBuffer(t *testing.T) { + b := Base{ + Features: Features{ + Enabled: FeaturesEnabled{}, + }, + Config: &config.ExchangeConfig{ + Features: &config.FeaturesConfig{ + Enabled: config.FeaturesEnabledConfig{}, + }, + }, + } + err := b.AddTradesToBuffer() + if err != nil { + t.Error(err) + } + + b.SetSaveTradeDataStatus(true) + err = b.AddTradesToBuffer() + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/exchange_types.go b/exchanges/exchange_types.go index 38c9cbe2..a0c622fd 100644 --- a/exchanges/exchange_types.go +++ b/exchanges/exchange_types.go @@ -1,6 +1,7 @@ package exchange import ( + "sync" "time" "github.com/thrasher-corp/gocryptotrader/config" @@ -108,19 +109,6 @@ type FeeBuilder struct { Amount float64 } -// TradeHistory holds exchange history data -type TradeHistory struct { - Timestamp time.Time - TID string - Price float64 - Amount float64 - Exchange string - Type string - Side string - Fee float64 - Description string -} - // FundHistory holds exchange funding history data type FundHistory struct { ExchangeName string @@ -150,6 +138,7 @@ type Features struct { type FeaturesEnabled struct { AutoPairUpdates bool Kline kline.ExchangeCapabilitiesEnabled + SaveTradeData bool } // FeaturesSupported stores the exchanges supported features @@ -214,5 +203,6 @@ type Base struct { WebsocketOrderbookBufferLimit int64 Websocket *stream.Websocket *request.Requester - Config *config.ExchangeConfig + Config *config.ExchangeConfig + settingsMutex sync.RWMutex } diff --git a/exchanges/exmo/exmo_test.go b/exchanges/exmo/exmo_test.go index ce60ee0b..ce20614c 100644 --- a/exchanges/exmo/exmo_test.go +++ b/exchanges/exmo/exmo_test.go @@ -4,6 +4,7 @@ import ( "log" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" @@ -443,3 +444,27 @@ func TestGetDepositAddress(t *testing.T) { } } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_USD") + if err != nil { + t.Fatal(err) + } + _, err = e.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_USD") + if err != nil { + t.Fatal(err) + } + _, err = e.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/exmo/exmo_types.go b/exchanges/exmo/exmo_types.go index aaceb963..6ee01fa2 100644 --- a/exchanges/exmo/exmo_types.go +++ b/exchanges/exmo/exmo_types.go @@ -5,7 +5,7 @@ import "github.com/thrasher-corp/gocryptotrader/currency" // Trades holds trade data type Trades struct { TradeID int64 `json:"trade_id"` - Type string `json:"string"` + Type string `json:"type"` Quantity float64 `json:"quantity,string"` Price float64 `json:"price,string"` Amount float64 `json:"amount,string"` diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index c9e853df..5c4bd57d 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -3,6 +3,7 @@ package exmo import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -361,9 +363,50 @@ func (e *EXMO) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (e *EXMO) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (e *EXMO) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = e.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData map[string][]Trades + tradeData, err = e.GetTrades(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + mapData := tradeData[p.String()] + for i := range mapData { + var side order.Side + side, err = order.StringToOrderSide(mapData[i].Type) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: e.Name, + TID: strconv.FormatInt(mapData[i].TradeID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: mapData[i].Price, + Amount: mapData[i].Quantity, + Timestamp: time.Unix(mapData[i].Date, 0), + }) + } + + err = e.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (e *EXMO) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/ftx/ftx.go b/exchanges/ftx/ftx.go index 3199f9a5..f170801f 100644 --- a/exchanges/ftx/ftx.go +++ b/exchanges/ftx/ftx.go @@ -144,19 +144,19 @@ func (f *FTX) GetOrderbook(marketName string, depth int64) (OrderbookData, error } // GetTrades gets trades based on the conditions specified -func (f *FTX) GetTrades(marketName string, startTime, endTime time.Time, limit int64) ([]TradeData, error) { +func (f *FTX) GetTrades(marketName string, startTime, endTime, limit int64) ([]TradeData, error) { strLimit := strconv.FormatInt(limit, 10) params := url.Values{} params.Set("limit", strLimit) resp := struct { Data []TradeData `json:"result"` }{} - if !startTime.IsZero() && !endTime.IsZero() { - if startTime.After(endTime) { + if startTime > 0 && endTime > 0 { + if startTime >= (endTime) { return resp.Data, errors.New("startTime cannot be after endTime") } - params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10)) - params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) + params.Set("start_time", strconv.FormatInt(startTime, 10)) + params.Set("end_time", strconv.FormatInt(endTime, 10)) } return resp.Data, f.SendHTTPRequest(fmt.Sprintf(ftxAPIURL+getTrades, marketName)+params.Encode(), &resp) diff --git a/exchanges/ftx/ftx_test.go b/exchanges/ftx/ftx_test.go index 9274f2a5..322fd207 100644 --- a/exchanges/ftx/ftx_test.go +++ b/exchanges/ftx/ftx_test.go @@ -91,15 +91,15 @@ func TestGetOrderbook(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := f.GetTrades(spotPair, time.Time{}, time.Time{}, 200) + _, err := f.GetTrades(spotPair, 0, 0, 200) if err != nil { t.Error(err) } - _, err = f.GetTrades(spotPair, time.Time{}, time.Time{}, 5) + _, err = f.GetTrades(spotPair, 0, 0, 5) if err != nil { t.Error(err) } - _, err = f.GetTrades(spotPair, time.Unix(1559901511, 0), time.Unix(1559881511, 0), 5) + _, err = f.GetTrades(spotPair, 1559901511, 1559881511, 5) if err == nil { t.Error(err) } @@ -1150,23 +1150,38 @@ func TestAcceptOTCQuote(t *testing.T) { } } -func TestGetExchangeHistory(t *testing.T) { +func TestGetHistoricTrades(t *testing.T) { t.Parallel() - p, err := currency.NewPairFromString("ADA-PERP") - if err != nil { - t.Fatal(err) + assets := f.GetAssetTypes() + for i := range assets { + enabledPairs, err := f.GetEnabledPairs(assets[i]) + if err != nil { + t.Fatal(err) + } + _, err = f.GetHistoricTrades(enabledPairs.GetRandomPair(), assets[i], time.Now().Add(-time.Minute*15), time.Now()) + if err != nil { + t.Error(err) + } + // longer term + _, err = f.GetHistoricTrades(enabledPairs.GetRandomPair(), assets[i], time.Now().Add(-time.Minute*60*310), time.Now().Add(-time.Minute*60*300)) + if err != nil { + t.Error(err) + } } - a, err := f.GetPairAssetType(p) - if err != nil { - t.Error(err) - } - _, err = f.GetExchangeHistory(p, a, time.Now().Add(-time.Minute*500), time.Now()) - if err != nil { - t.Error(err) - } - _, err = f.GetExchangeHistory(p, a, time.Time{}, time.Now()) - if err == nil { - t.Error("error cannot be nil ") +} + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + assets := f.GetAssetTypes() + for i := range assets { + enabledPairs, err := f.GetEnabledPairs(assets[i]) + if err != nil { + t.Fatal(err) + } + _, err = f.GetRecentTrades(enabledPairs.GetRandomPair(), assets[i]) + if err != nil { + t.Error(err) + } } } diff --git a/exchanges/ftx/ftx_websocket.go b/exchanges/ftx/ftx_websocket.go index 97fd83e1..c24331fc 100644 --- a/exchanges/ftx/ftx_websocket.go +++ b/exchanges/ftx/ftx_websocket.go @@ -21,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -292,11 +293,15 @@ func (f *FTX) wsHandleData(respRaw []byte) error { return err } case wsTrades: + if !f.IsSaveTradeDataEnabled() { + return nil + } var resultData WsTradeDataStore err = json.Unmarshal(respRaw, &resultData) if err != nil { return err } + var trades []trade.Data for z := range resultData.TradeData { var oSide order.Side oSide, err = order.StringToOrderSide(resultData.TradeData[z].Side) @@ -306,7 +311,7 @@ func (f *FTX) wsHandleData(respRaw []byte) error { Err: err, } } - f.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ Timestamp: resultData.TradeData[z].Time, CurrencyPair: p, AssetType: a, @@ -314,8 +319,10 @@ func (f *FTX) wsHandleData(respRaw []byte) error { Price: resultData.TradeData[z].Price, Amount: resultData.TradeData[z].Size, Side: oSide, - } + TID: strconv.FormatInt(resultData.TradeData[z].ID, 10), + }) } + return trade.AddTradesToBuffer(f.Name, trades...) case wsOrders: var resultData WsOrderDataStore err = json.Unmarshal(respRaw, &resultData) diff --git a/exchanges/ftx/ftx_wrapper.go b/exchanges/ftx/ftx_wrapper.go index b3da0133..e5e062fa 100644 --- a/exchanges/ftx/ftx_wrapper.go +++ b/exchanges/ftx/ftx_wrapper.go @@ -2,6 +2,7 @@ package ftx import ( "fmt" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -436,8 +438,13 @@ func (f *FTX) GetFundingHistory() ([]exchange.FundHistory, error) { return resp, nil } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (f *FTX) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { +// GetRecentTrades returns the most recent trades for a currency and asset +func (f *FTX) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return f.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (f *FTX) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { if timestampStart.Equal(timestampEnd) || timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) || @@ -446,51 +453,65 @@ func (f *FTX) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestam timestampStart, timestampEnd) } + var err error + p, err = f.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } - marketName, err := f.FormatExchangeCurrency(p, assetType) - if err != nil { - return nil, err - } - var resp []exchange.TradeHistory - trades, err := f.GetTrades(marketName.String(), - time.Unix(timestampStart.Unix(), 0), - time.Unix(timestampEnd.Unix(), 0), - 100) - if err != nil { - return nil, err - } + ts := timestampStart + var resp []trade.Data + limit := 100 +allTrades: for { - var tempResp exchange.TradeHistory - if len(trades) > 0 { - tempResp.Amount = trades[0].Size - tempResp.Price = trades[0].Price - tempResp.Exchange = f.Name - tempResp.Timestamp = trades[0].Time - tempResp.TID = strconv.FormatInt(trades[0].ID, 10) - tempResp.Side = trades[0].Side - resp = append(resp, tempResp) - } - for y := 1; y < len(trades); y++ { - tempResp.Amount = trades[y].Size - tempResp.Price = trades[y].Price - tempResp.Exchange = f.Name - tempResp.Timestamp = trades[y].Time - tempResp.TID = strconv.FormatInt(trades[y].ID, 10) - tempResp.Side = trades[y].Side - resp = append(resp, tempResp) - } - if len(trades) != 100 { - break - } - trades, err = f.GetTrades(marketName.String(), - time.Unix(timestampStart.Unix(), 0), - time.Unix(trades[len(trades)-1].Time.Unix(), 0), + var trades []TradeData + trades, err = f.GetTrades(p.String(), + ts.Unix(), + timestampEnd.Unix(), 100) if err != nil { - return resp, err + return nil, err + } + + for i := 0; i < len(trades); i++ { + if trades[i].Time.Before(timestampStart) || trades[i].Time.After(timestampEnd) { + break allTrades + } + var side order.Side + side, err = order.StringToOrderSide(trades[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + TID: strconv.FormatInt(trades[i].ID, 10), + Exchange: f.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: trades[i].Price, + Amount: trades[i].Size, + Timestamp: trades[i].Time, + }) + if i == len(trades)-1 { + if ts.Equal(trades[i].Time) { + // reached end of trades to crawl + break allTrades + } + ts = trades[i].Time + } + } + if len(trades) != limit { + break allTrades } } - return resp, nil + + err = f.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return trade.FilterTradesByTime(resp, timestampStart, timestampEnd), nil } // SubmitOrder submits a new order diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go index b0f19d2c..1f54db81 100644 --- a/exchanges/gateio/gateio.go +++ b/exchanges/gateio/gateio.go @@ -35,6 +35,7 @@ const ( gateioTradeHistory = "private/tradeHistory" gateioDepositAddress = "private/depositAddress" gateioTicker = "ticker" + gateioTrades = "tradeHistory" gateioTickers = "tickers" gateioOrderbook = "orderBook" @@ -121,6 +122,17 @@ func (g *Gateio) GetTickers() (map[string]TickerResponse, error) { return resp, nil } +// GetTrades returns trades for symbols +func (g *Gateio) GetTrades(symbol string) (TradeHistory, error) { + urlPath := fmt.Sprintf("%s/%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioTrades, symbol) + var resp TradeHistory + err := g.SendHTTPRequest(urlPath, &resp) + if err != nil { + return TradeHistory{}, err + } + return resp, nil +} + // GetOrderbook returns the orderbook data for a suppled symbol func (g *Gateio) GetOrderbook(symbol string) (Orderbook, error) { urlPath := fmt.Sprintf("%s/%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioOrderbook, symbol) diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index 31304b6b..a20c0809 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -175,6 +175,14 @@ func setFeeBuilder() *exchange.FeeBuilder { } } +func TestGetTradeHistory(t *testing.T) { + _, err := g.GetTrades(currency.NewPairWithDelimiter(currency.BTC.String(), + currency.USDT.String(), "_").String()) + if err != nil { + t.Error(err) + } +} + // TestGetFeeByTypeOfflineTradeFee logic test func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { var feeBuilder = setFeeBuilder() @@ -809,3 +817,27 @@ func TestGenerateDefaultSubscriptions(t *testing.T) { t.Fatal("unexpected payload length") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = g.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = g.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/gateio/gateio_types.go b/exchanges/gateio/gateio_types.go index 184923b4..8012dc4d 100644 --- a/exchanges/gateio/gateio_types.go +++ b/exchanges/gateio/gateio_types.go @@ -162,6 +162,7 @@ type TradesResponse struct { OrderID int64 `json:"orderNumber"` Pair string `json:"pair"` Type string `json:"type"` + Side string `json:"side"` Rate float64 `json:"rate,string"` Amount float64 `json:"amount,string"` Total float64 `json:"total"` @@ -506,3 +507,21 @@ type wsOrderUpdate struct { Method string `json:"method"` Params []interface{} `json:"params"` } + +// TradeHistory contains trade history data +type TradeHistory struct { + Elapsed string `json:"elapsed"` + Result bool `json:"result,string"` + Data []TradeHistoryEntry `json:"data"` +} + +// TradeHistoryEntry contains an individual trade +type TradeHistoryEntry struct { + Amount float64 `json:"amount,string"` + Date string `json:"date"` + Rate float64 `json:"rate,string"` + Timestamp int64 `json:"timestamp,string"` + Total float64 `json:"total,string"` + TradeID string `json:"tradeID"` + Type string `json:"type"` +} diff --git a/exchanges/gateio/gateio_websocket.go b/exchanges/gateio/gateio_websocket.go index 40a400c3..1f028321 100644 --- a/exchanges/gateio/gateio_websocket.go +++ b/exchanges/gateio/gateio_websocket.go @@ -21,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" ) const ( @@ -170,9 +171,12 @@ func (g *Gateio) wsHandleData(respRaw []byte) error { } case strings.Contains(result.Method, "trades"): - var trades []WebsocketTrade + if !g.IsSaveTradeDataEnabled() { + return nil + } + var tradeData []WebsocketTrade var c string - err = json.Unmarshal(result.Params[1], &trades) + err = json.Unmarshal(result.Params[1], &tradeData) if err != nil { return err } @@ -186,26 +190,28 @@ func (g *Gateio) wsHandleData(respRaw []byte) error { if err != nil { return err } - - for i := range trades { + var trades []trade.Data + for i := range tradeData { var tSide order.Side - tSide, err = order.StringToOrderSide(trades[i].Type) + tSide, err = order.StringToOrderSide(tradeData[i].Type) if err != nil { g.Websocket.DataHandler <- order.ClassificationError{ Exchange: g.Name, Err: err, } } - g.Websocket.DataHandler <- stream.TradeData{ - Timestamp: time.Now(), + trades = append(trades, trade.Data{ + Timestamp: convert.TimeFromUnixTimestampDecimal(tradeData[i].Time), CurrencyPair: p, AssetType: asset.Spot, Exchange: g.Name, - Price: trades[i].Price, - Amount: trades[i].Amount, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, Side: tSide, - } + TID: strconv.FormatInt(tradeData[i].ID, 10), + }) } + return trade.AddTradesToBuffer(g.Name, trades...) case strings.Contains(result.Method, "balance.update"): var balance wsBalanceSubscription err = json.Unmarshal(respRaw, &balance) diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go index 6797b464..8e1303bf 100644 --- a/exchanges/gateio/gateio_wrapper.go +++ b/exchanges/gateio/gateio_wrapper.go @@ -3,6 +3,7 @@ package gateio import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -415,9 +417,49 @@ func (g *Gateio) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (g *Gateio) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (g *Gateio) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = g.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData TradeHistory + tradeData, err = g.GetTrades(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData.Data { + var side order.Side + side, err = order.StringToOrderSide(tradeData.Data[i].Type) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: g.Name, + TID: tradeData.Data[i].TradeID, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData.Data[i].Rate, + Amount: tradeData.Data[i].Amount, + Timestamp: time.Unix(tradeData.Data[i].Timestamp, 0), + }) + } + + err = g.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (g *Gateio) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index 98cf8eed..6778df5e 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -107,7 +107,7 @@ func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook return orderbook, g.SendHTTPRequest(path, &orderbook) } -// GetTrades eturn the trades that have executed since the specified timestamp. +// GetTrades return the trades that have executed since the specified timestamp. // Timestamps are either seconds or milliseconds since the epoch (1970-01-01). // // currencyPair - example "btcusd" @@ -116,7 +116,17 @@ func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook // limit_trades integer Optional. The maximum number of trades to return. // include_breaks boolean Optional. Whether to display broken trades. False by // default. Can be '1' or 'true' to activate -func (g *Gemini) GetTrades(currencyPair string, params url.Values) ([]Trade, error) { +func (g *Gemini) GetTrades(currencyPair string, since, limit int64, includeBreaks bool) ([]Trade, error) { + params := url.Values{} + if since > 0 { + params.Add("since", strconv.FormatInt(since, 10)) + } + if limit > 0 { + params.Add("limit_trades", strconv.FormatInt(limit, 10)) + } + if includeBreaks { + params.Add("include_breaks", strconv.FormatBool(true)) + } path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiTrades, currencyPair), params) var trades []Trade diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go index 4045010a..b6f342a0 100644 --- a/exchanges/gemini/gemini_test.go +++ b/exchanges/gemini/gemini_test.go @@ -60,7 +60,7 @@ func TestGetOrderbook(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := g.GetTrades(testCurrency, url.Values{}) + _, err := g.GetTrades(testCurrency, 0, 0, false) if err != nil { t.Error("GetTrades() error", err) } @@ -1111,3 +1111,33 @@ func TestResponseToOrderType(t *testing.T) { } } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testCurrency) + if err != nil { + t.Fatal(err) + } + _, err = g.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testCurrency) + if err != nil { + t.Fatal(err) + } + tStart := time.Date(2020, 6, 6, 0, 0, 0, 0, time.UTC) + tEnd := time.Date(2020, 6, 7, 0, 0, 0, 0, time.UTC) + if !mockTests { + tStart = time.Date(2020, time.Now().Month(), 6, 0, 0, 0, 0, time.UTC) + tEnd = time.Date(2020, time.Now().Month(), 7, 0, 0, 0, 0, time.UTC) + } + _, err = g.GetHistoricTrades(currencyPair, asset.Spot, tStart, tEnd) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/gemini/gemini_types.go b/exchanges/gemini/gemini_types.go index abea9703..d0cc07cd 100644 --- a/exchanges/gemini/gemini_types.go +++ b/exchanges/gemini/gemini_types.go @@ -51,7 +51,7 @@ type Trade struct { Price float64 `json:"price,string"` Amount float64 `json:"amount,string"` Exchange string `json:"exchange"` - Side string `json:"type"` + Type string `json:"type"` } // Auction is generalized response type @@ -241,6 +241,7 @@ type Event struct { Remaining float64 `json:"remaining,string"` Side string `json:"side"` MakerSide string `json:"makerSide"` + ID int64 `json:"tid"` Amount float64 `json:"amount,string"` } diff --git a/exchanges/gemini/gemini_websocket.go b/exchanges/gemini/gemini_websocket.go index 0915f38e..3953cc1b 100644 --- a/exchanges/gemini/gemini_websocket.go +++ b/exchanges/gemini/gemini_websocket.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" "net/url" + "strconv" "strings" "time" @@ -20,13 +21,13 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) const ( geminiWebsocketEndpoint = "wss://api.gemini.com/v1/" geminiWebsocketSandboxEndpoint = "wss://api.sandbox.gemini.com/v1/" - geminiWsEvent = "event" geminiWsMarketData = "marketdata" geminiWsOrderEvents = "order/events" ) @@ -401,6 +402,7 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa } } else { var asks, bids []orderbook.Item + var trades []trade.Data for i := range result.Events { switch result.Events[i].Type { case "trade": @@ -411,7 +413,7 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa Err: err, } } - g.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ Timestamp: time.Unix(0, result.TimestampMS*int64(time.Millisecond)), CurrencyPair: pair, AssetType: asset.Spot, @@ -419,7 +421,8 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa Price: result.Events[i].Price, Amount: result.Events[i].Amount, Side: tSide, - } + TID: strconv.FormatInt(result.Events[i].ID, 10), + }) case "change": item := orderbook.Item{ Amount: result.Events[i].Remaining, @@ -434,6 +437,12 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa g.Websocket.DataHandler <- fmt.Errorf("%s - Unhandled websocket update: %+v", g.Name, result) } } + if len(trades) > 0 && g.IsSaveTradeDataEnabled() { + err := trade.AddTradesToBuffer(g.Name, trades...) + if err != nil { + g.Websocket.DataHandler <- err + } + } if len(asks) == 0 && len(bids) == 0 { return } diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 4fe38ec5..c365c602 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -2,7 +2,9 @@ package gemini import ( "errors" + "fmt" "net/url" + "sort" "strconv" "strings" "sync" @@ -21,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -328,9 +331,72 @@ func (g *Gemini) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (g *Gemini) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (g *Gemini) GetRecentTrades(currencyPair currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return g.GetHistoricTrades(currencyPair, assetType, time.Time{}, time.Time{}) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (g *Gemini) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + p, err = g.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + ts := timestampStart + limit := 500 +allTrades: + for { + var tradeData []Trade + tradeData, err = g.GetTrades(p.String(), ts.Unix(), int64(limit), false) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTS := time.Unix(tradeData[i].Timestamp, 0) + if tradeTS.After(timestampEnd) && !timestampEnd.IsZero() { + break allTrades + } + + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Type) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: g.Name, + TID: strconv.FormatInt(tradeData[i].TID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTS, + }) + if i == len(tradeData)-1 { + if ts == tradeTS { + break allTrades + } + ts = tradeTS + } + } + if len(tradeData) != limit { + break allTrades + } + } + + err = g.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + resp = trade.FilterTradesByTime(resp, timestampStart, timestampEnd) + + sort.Sort(trade.ByDate(resp)) + return resp, nil } // SubmitOrder submits a new order diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go index 6b36f1f1..4995b904 100644 --- a/exchanges/hitbtc/hitbtc.go +++ b/exchanges/hitbtc/hitbtc.go @@ -128,37 +128,25 @@ func (h *HitBTC) GetTickers() ([]TickerResponse, error) { } // GetTrades returns trades from hitbtc -func (h *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort string) ([]TradeHistory, error) { - // start Number or Datetime - // end Number or Datetime - // limit Number - // offset Number - // by Filtration definition. Accepted values: id, timestamh. Default timestamp - // sort Default DESC - vals := url.Values{} - - if from != "" { - vals.Set("from", from) +func (h *HitBTC) GetTrades(currencyPair, by, sort string, from, till, limit, offset int64) ([]TradeHistory, error) { + urlValues := url.Values{} + if from > 0 { + urlValues.Set("from", strconv.FormatInt(from, 10)) } - - if till != "" { - vals.Set("till", till) + if till > 0 { + urlValues.Set("till", strconv.FormatInt(till, 10)) } - - if limit != "" { - vals.Set("limit", limit) + if limit > 0 { + urlValues.Set("limit", strconv.FormatInt(limit, 10)) } - - if offset != "" { - vals.Set("offset", offset) + if offset > 0 { + urlValues.Set("offset", strconv.FormatInt(offset, 10)) } - if by != "" { - vals.Set("by", by) + urlValues.Set("by", by) } - if sort != "" { - vals.Set("sort", sort) + urlValues.Set("sort", sort) } var resp []TradeHistory @@ -166,7 +154,7 @@ func (h *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort str h.API.Endpoints.URL, apiV2Trades, currencyPair, - vals.Encode()) + urlValues.Encode()) return resp, h.SendHTTPRequest(path, &resp) } diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go index e4b05ad6..3e3001cc 100644 --- a/exchanges/hitbtc/hitbtc_test.go +++ b/exchanges/hitbtc/hitbtc_test.go @@ -62,7 +62,7 @@ func TestGetOrderbook(t *testing.T) { } func TestGetTrades(t *testing.T) { - _, err := h.GetTrades("BTCUSD", "", "", "", "", "", "") + _, err := h.GetTrades("BTCUSD", "", "", 0, 0, 0, 0) if err != nil { t.Error("Test faild - HitBTC GetTradeHistory() error", err) } @@ -992,3 +992,32 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = h.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = h.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } + // longer term + _, err = h.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*60*200), time.Now().Add(-time.Minute*60*199)) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index aed37f5b..07a02110 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -21,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -194,18 +195,43 @@ func (h *HitBTC) wsHandleData(respRaw []byte) error { if err != nil { return err } - case "snapshotTrades": + case "snapshotTrades", "updateTrades": + if !h.IsSaveTradeDataEnabled() { + return nil + } var tradeSnapshot WsTrade err := json.Unmarshal(respRaw, &tradeSnapshot) if err != nil { return err } - case "updateTrades": - var tradeUpdates WsTrade - err := json.Unmarshal(respRaw, &tradeUpdates) + var trades []trade.Data + p, err := currency.NewPairFromString(tradeSnapshot.Params.Symbol) if err != nil { - return err + return &order.ClassificationError{ + Exchange: h.Name, + Err: err, + } } + for i := range tradeSnapshot.Params.Data { + side, err := order.StringToOrderSide(tradeSnapshot.Params.Data[i].Side) + if err != nil { + return &order.ClassificationError{ + Exchange: h.Name, + Err: err, + } + } + trades = append(trades, trade.Data{ + Timestamp: tradeSnapshot.Params.Data[i].Timestamp, + Exchange: h.Name, + CurrencyPair: p, + AssetType: asset.Spot, + Price: tradeSnapshot.Params.Data[i].Price, + Amount: tradeSnapshot.Params.Data[i].Quantity, + Side: side, + TID: strconv.FormatInt(tradeSnapshot.Params.Data[i].ID, 10), + }) + } + return trade.AddTradesToBuffer(h.Name, trades...) case "activeOrders": var o wsActiveOrdersResponse err := json.Unmarshal(respRaw, &o) diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index e82a4259..fe348f35 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -3,6 +3,7 @@ package hitbtc import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -448,9 +450,70 @@ func (h *HitBTC) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (h *HitBTC) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (h *HitBTC) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return h.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (h *HitBTC) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + p, err = h.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + ts := timestampStart + var resp []trade.Data + limit := 1000 +allTrades: + for { + var tradeData []TradeHistory + tradeData, err = h.GetTrades(p.String(), "", "", ts.UnixNano()/int64(time.Millisecond), timestampEnd.UnixNano()/int64(time.Millisecond), int64(limit), 0) + if err != nil { + return nil, err + } + for i := range tradeData { + if tradeData[i].Timestamp.Before(timestampStart) || tradeData[i].Timestamp.After(timestampEnd) { + break allTrades + } + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: h.Name, + TID: strconv.FormatInt(tradeData[i].ID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Quantity, + Timestamp: tradeData[i].Timestamp, + }) + if i == len(tradeData)-1 { + if ts.Equal(tradeData[i].Timestamp) { + // reached end of trades to crawl + break allTrades + } + ts = tradeData[i].Timestamp + } + } + if len(tradeData) != limit { + break allTrades + } + } + + err = h.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil } // SubmitOrder submits a new order diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index c0fc5d8a..c0f3cdca 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -167,7 +167,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) { // // symbol: string of currency pair func (h *HUOBI) GetLatestSpotPrice(symbol string) (float64, error) { - list, err := h.GetTradeHistory(symbol, "1") + list, err := h.GetTradeHistory(symbol, 1) if err != nil { return 0, err @@ -180,12 +180,12 @@ func (h *HUOBI) GetLatestSpotPrice(symbol string) (float64, error) { } // GetTradeHistory returns the trades for the specified symbol -func (h *HUOBI) GetTradeHistory(symbol, size string) ([]TradeHistory, error) { +func (h *HUOBI) GetTradeHistory(symbol string, size int64) ([]TradeHistory, error) { vals := url.Values{} vals.Set("symbol", symbol) - if size != "" { - vals.Set("size", size) + if size > 0 { + vals.Set("size", strconv.FormatInt(size, 10)) } type response struct { diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index e20b4e60..1edbdcad 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -166,7 +166,7 @@ func TestGetLatestSpotPrice(t *testing.T) { func TestGetTradeHistory(t *testing.T) { t.Parallel() - _, err := h.GetTradeHistory(testSymbol, "50") + _, err := h.GetTradeHistory(testSymbol, 50) if err != nil { t.Errorf("Huobi TestGetTradeHistory: %s", err) } @@ -1109,3 +1109,27 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-USDT") + if err != nil { + t.Fatal(err) + } + _, err = h.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testSymbol) + if err != nil { + t.Fatal(err) + } + _, err = h.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/huobi/huobi_types.go b/exchanges/huobi/huobi_types.go index b435b0c3..b67c216a 100644 --- a/exchanges/huobi/huobi_types.go +++ b/exchanges/huobi/huobi_types.go @@ -93,7 +93,7 @@ type Orderbook struct { // Trade stores the trade data type Trade struct { - ID float64 `json:"id"` + TradeID float64 `json:"trade-id"` Price float64 `json:"price"` Amount float64 `json:"amount"` Direction string `json:"direction"` @@ -391,7 +391,7 @@ type WsTrade struct { Data []struct { Amount float64 `json:"amount"` Timestamp int64 `json:"ts"` - ID float64 `json:"id"` + TradeID float64 `json:"tradeId"` Price float64 `json:"price"` Direction string `json:"direction"` } `json:"data"` diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index 9bebc259..e0bbe75c 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -344,35 +345,40 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error { Interval: data[3], } case strings.Contains(init.Channel, "trade.detail"): - var trade WsTrade - err := json.Unmarshal(respRaw, &trade) + if !h.IsSaveTradeDataEnabled() { + return nil + } + var t WsTrade + err := json.Unmarshal(respRaw, &t) if err != nil { return err } - data := strings.Split(trade.Channel, ".") + data := strings.Split(t.Channel, ".") var p currency.Pair var a asset.Item p, a, err = h.GetRequestFormattedPairAndAssetType(data[1]) if err != nil { return err } - - for i := range trade.Tick.Data { + var trades []trade.Data + for i := range t.Tick.Data { side := order.Buy - if trade.Tick.Data[i].Direction != "buy" { + if t.Tick.Data[i].Direction != "buy" { side = order.Sell } - h.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ Exchange: h.Name, AssetType: a, CurrencyPair: p, Timestamp: time.Unix(0, - trade.Tick.Data[i].Timestamp*int64(time.Millisecond)), - Amount: trade.Tick.Data[i].Amount, - Price: trade.Tick.Data[i].Price, + t.Tick.Data[i].Timestamp*int64(time.Millisecond)), + Amount: t.Tick.Data[i].Amount, + Price: t.Tick.Data[i].Price, Side: side, - } + TID: strconv.FormatFloat(t.Tick.Data[i].TradeID, 'f', -1, 64), + }) } + return trade.AddTradesToBuffer(h.Name, trades...) case strings.Contains(init.Channel, "detail"), strings.Contains(init.Rep, "detail"): var wsTicker WsTick diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index 8f906f0b..25d99efd 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -3,6 +3,7 @@ package huobi import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -543,9 +545,51 @@ func (h *HUOBI) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (h *HUOBI) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (h *HUOBI) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = h.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData []TradeHistory + tradeData, err = h.GetTradeHistory(p.String(), 2000) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + for j := range tradeData[i].Trades { + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Trades[j].Direction) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: h.Name, + TID: strconv.FormatFloat(tradeData[i].Trades[j].TradeID, 'f', -1, 64), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Trades[j].Price, + Amount: tradeData[i].Trades[j].Amount, + Timestamp: time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond)), + }) + } + } + + err = h.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (h *HUOBI) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/interfaces.go b/exchanges/interfaces.go index 5d1302b7..36fc106c 100644 --- a/exchanges/interfaces.go +++ b/exchanges/interfaces.go @@ -13,6 +13,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -39,7 +40,8 @@ type IBotExchange interface { GetAuthenticatedAPISupport(endpoint uint8) bool SetPairs(pairs currency.Pairs, a asset.Item, enabled bool) error GetAssetTypes() asset.Items - GetExchangeHistory(p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]TradeHistory, error) + GetRecentTrades(p currency.Pair, a asset.Item) ([]trade.Data, error) + GetHistoricTrades(p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]trade.Data, error) SupportsAutoPairUpdates() bool SupportsRESTTickerBatchUpdates() bool GetFeeByType(f *FeeBuilder) (float64, error) diff --git a/exchanges/itbit/itbit.go b/exchanges/itbit/itbit.go index cb4180ce..d1fa74cf 100644 --- a/exchanges/itbit/itbit.go +++ b/exchanges/itbit/itbit.go @@ -63,7 +63,11 @@ func (i *ItBit) GetOrderbook(currencyPair string) (OrderbookResponse, error) { // timestamp - matchNumber, only executions after this will be returned func (i *ItBit) GetTradeHistory(currencyPair, tradeID string) (Trades, error) { response := Trades{} - req := "trades?since=" + tradeID + + var req = itbitTrades + if tradeID != "" { + req += "?since=" + tradeID + } path := fmt.Sprintf("%s/%s/%s/%s", i.API.Endpoints.URL, itbitMarkets, currencyPair, req) return response, i.SendHTTPRequest(path, &response) diff --git a/exchanges/itbit/itbit_test.go b/exchanges/itbit/itbit_test.go index aa887268..3802f0a3 100644 --- a/exchanges/itbit/itbit_test.go +++ b/exchanges/itbit/itbit_test.go @@ -5,6 +5,7 @@ import ( "net/url" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" @@ -444,3 +445,27 @@ func TestGetDepositAddress(t *testing.T) { t.Error("GetDepositAddress() error cannot be nil") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("XBTUSD") + if err != nil { + t.Fatal(err) + } + _, err = i.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("XBTUSD") + if err != nil { + t.Fatal(err) + } + _, err = i.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/itbit/itbit_types.go b/exchanges/itbit/itbit_types.go index 6408c3cf..30986d62 100644 --- a/exchanges/itbit/itbit_types.go +++ b/exchanges/itbit/itbit_types.go @@ -40,10 +40,10 @@ type OrderbookResponse struct { // Trades holds recent trades with associated information type Trades struct { RecentTrades []struct { - Timestamp string `json:"timestamp"` - MatchNumber string `json:"matchNumber"` - Price float64 `json:"price,string"` - Amount float64 `json:"amount,string"` + Timestamp time.Time `json:"timestamp"` + MatchNumber string `json:"matchNumber"` + Price float64 `json:"price,string"` + Amount float64 `json:"amount,string"` } `json:"recentTrades"` } diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index 8a81ea9e..49e9f59f 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -3,6 +3,7 @@ package itbit import ( "fmt" "net/url" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -306,9 +308,44 @@ func (i *ItBit) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (i *ItBit) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (i *ItBit) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = i.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData Trades + tradeData, err = i.GetTradeHistory(p.String(), "") + if err != nil { + return nil, err + } + var resp []trade.Data + for x := range tradeData.RecentTrades { + resp = append(resp, trade.Data{ + Exchange: i.Name, + TID: tradeData.RecentTrades[x].MatchNumber, + CurrencyPair: p, + AssetType: assetType, + Price: tradeData.RecentTrades[x].Price, + Amount: tradeData.RecentTrades[x].Amount, + Timestamp: tradeData.RecentTrades[x].Timestamp, + }) + } + + err = i.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (i *ItBit) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + // cannot do time based retrieval of trade data + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/kline/kline_datastorage.go b/exchanges/kline/kline_datastorage.go index 95ae6491..b7e15375 100644 --- a/exchanges/kline/kline_datastorage.go +++ b/exchanges/kline/kline_datastorage.go @@ -29,6 +29,7 @@ func LoadFromDatabase(exchange string, pair currency.Pair, a asset.Item, interva Exchange: exchange, Pair: pair, Interval: interval, + Asset: a, } for x := range retCandle.Candles { @@ -45,7 +46,7 @@ func LoadFromDatabase(exchange string, pair currency.Pair, a asset.Item, interva } // StoreInDatabase returns Item from database seeded data -func StoreInDatabase(in *Item) (uint64, error) { +func StoreInDatabase(in *Item, force bool) (uint64, error) { if in.Exchange == "" { return 0, errors.New("name cannot be blank") } @@ -77,7 +78,7 @@ func StoreInDatabase(in *Item) (uint64, error) { for x := range in.Candles { databaseCandles.Candles = append(databaseCandles.Candles, candle.Candle{ - Timestamp: in.Candles[x].Time, + Timestamp: in.Candles[x].Time.Truncate(in.Interval.Duration()), Open: in.Candles[x].Open, High: in.Candles[x].High, Low: in.Candles[x].Low, @@ -85,6 +86,12 @@ func StoreInDatabase(in *Item) (uint64, error) { Volume: in.Candles[x].Volume, }) } + if force { + _, err := candle.DeleteCandles(&databaseCandles) + if err != nil { + return 0, err + } + } return candle.Insert(&databaseCandles) } diff --git a/exchanges/kline/kline_test.go b/exchanges/kline/kline_test.go index 5aac29b6..80bd6087 100644 --- a/exchanges/kline/kline_test.go +++ b/exchanges/kline/kline_test.go @@ -508,7 +508,16 @@ func TestStoreInDatabase(t *testing.T) { if err != nil { t.Fatal(err) } - r, err := StoreInDatabase(&ohlcvData) + r, err := StoreInDatabase(&ohlcvData, false) + if err != nil { + t.Fatal(err) + } + + if r != 365 { + t.Fatalf("unexpected number inserted: %v", r) + } + + r, err = StoreInDatabase(&ohlcvData, true) if err != nil { t.Fatal(err) } diff --git a/exchanges/kline/kline_types.go b/exchanges/kline/kline_types.go index 20a39a9b..ae74071c 100644 --- a/exchanges/kline/kline_types.go +++ b/exchanges/kline/kline_types.go @@ -56,6 +56,21 @@ type Candle struct { Volume float64 } +// By Date allows for sorting candle entries by date +type ByDate []Candle + +func (b ByDate) Len() int { + return len(b) +} + +func (b ByDate) Less(i, j int) bool { + return b[i].Time.Before(b[j].Time) +} + +func (b ByDate) Swap(i, j int) { + b[i], b[j] = b[j], b[i] +} + // ExchangeCapabilitiesSupported all kline related exchange supported options type ExchangeCapabilitiesSupported struct { Intervals bool diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index af51ebb0..7eaa3547 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -11,6 +11,7 @@ import ( "sync" "time" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" @@ -341,30 +342,95 @@ func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) { err := k.SendHTTPRequest(path, &result) if err != nil { - return recentTrades, err + return nil, err } - data := result.(map[string]interface{}) - tradeInfo := data["result"].(map[string]interface{}) - - for _, x := range tradeInfo[symbol].([]interface{}) { - r := RecentTrades{} - for i, y := range x.([]interface{}) { - switch i { - case 0: - r.Price, _ = strconv.ParseFloat(y.(string), 64) - case 1: - r.Volume, _ = strconv.ParseFloat(y.(string), 64) - case 2: - r.Time = y.(float64) - case 3: - r.BuyOrSell = y.(string) - case 4: - r.MarketOrLimit = y.(string) - case 5: - r.Miscellaneous = y.(string) + data, ok := result.(map[string]interface{}) + if !ok { + return nil, errors.New("unable to parse trade data") + } + var dataError interface{} + dataError, ok = data["error"] + if ok { + var dataErrorInterface interface{} + dataErrorInterface, ok = dataError.(interface{}) + if ok { + var errorList []interface{} + errorList, ok = dataErrorInterface.([]interface{}) + if ok { + var errs common.Errors + for i := range errorList { + var errString string + errString, ok = errorList[i].(string) + if !ok { + continue + } + errs = append(errs, errors.New(errString)) + } + if len(errs) > 0 { + return nil, errs + } } } + } + + var resultField interface{} + resultField, ok = data["result"] + if !ok { + return nil, errors.New("unable to find field 'result'") + } + var tradeInfo map[string]interface{} + tradeInfo, ok = resultField.(map[string]interface{}) + if !ok { + return nil, errors.New("unable to parse field 'result'") + } + + var trades []interface{} + var tradesForSymbol interface{} + tradesForSymbol, ok = tradeInfo[symbol] + if !ok { + return nil, fmt.Errorf("no data returned for symbol %v", symbol) + } + + trades, ok = tradesForSymbol.([]interface{}) + if !ok { + return nil, fmt.Errorf("no trades returned for symbol %v", symbol) + } + + for _, x := range trades { + r := RecentTrades{} + var individualTrade []interface{} + individualTrade, ok = x.([]interface{}) + if !ok { + return nil, errors.New("unable to parse individual trade data") + } + if len(individualTrade) != 6 { + return nil, errors.New("unrecognised trade data received") + } + r.Price, err = strconv.ParseFloat(individualTrade[0].(string), 64) + if err != nil { + return nil, err + } + r.Volume, err = strconv.ParseFloat(individualTrade[1].(string), 64) + if err != nil { + return nil, err + } + r.Time, ok = individualTrade[2].(float64) + if !ok { + return nil, errors.New("unable to parse time for individual trade data") + } + r.BuyOrSell, ok = individualTrade[3].(string) + if !ok { + return nil, errors.New("unable to parse order side for individual trade data") + } + r.MarketOrLimit, ok = individualTrade[4].(string) + if !ok { + return nil, errors.New("unable to parse order type for individual trade data") + } + r.Miscellaneous, ok = individualTrade[5].(string) + if !ok { + return nil, errors.New("unable to parse misc field for individual trade data") + } recentTrades = append(recentTrades, r) } return recentTrades, nil diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index c2f1b4b3..1a02f857 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/gorilla/websocket" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/core" @@ -184,6 +185,11 @@ func TestGetTrades(t *testing.T) { if err != nil { t.Error("GetTrades() error", err) } + + _, err = k.GetTrades("MADEUP") + if err == nil { + t.Error("expected error") + } } // TestGetSpread API endpoint test @@ -1473,3 +1479,27 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("XBTUSD") + if err != nil { + t.Fatal(err) + } + _, err = k.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("XBTUSD") + if err != nil { + t.Fatal(err) + } + _, err = k.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index 1ee23723..4f119d74 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -284,21 +285,42 @@ func (k *Kraken) wsReadDataResponse(response WebsocketDataResponse) error { channelData := getSubscriptionChannelData(channelID) switch channelData.Subscription { case krakenWsTicker: - return k.wsProcessTickers(&channelData, response[1].(map[string]interface{})) + t, ok := response[1].(map[string]interface{}) + if !ok { + return errors.New("received invalid ticker data") + } + return k.wsProcessTickers(&channelData, t) case krakenWsOHLC: - return k.wsProcessCandles(&channelData, response[1].([]interface{})) + o, ok := response[1].([]interface{}) + if !ok { + return errors.New("received invalid OHLCV data") + } + return k.wsProcessCandles(&channelData, o) case krakenWsOrderbook: - return k.wsProcessOrderBook(&channelData, response[1].(map[string]interface{})) + ob, ok := response[1].(map[string]interface{}) + if !ok { + return errors.New("received invalid orderbook data") + } + return k.wsProcessOrderBook(&channelData, ob) case krakenWsSpread: - k.wsProcessSpread(&channelData, response[1].([]interface{})) + s, ok := response[1].([]interface{}) + if !ok { + return errors.New("received invalid spread data") + } + k.wsProcessSpread(&channelData, s) case krakenWsTrade: - k.wsProcessTrades(&channelData, response[1].([]interface{})) + t, ok := response[1].([]interface{}) + if !ok { + return errors.New("received invalid trade data") + } + return k.wsProcessTrades(&channelData, t) default: - return fmt.Errorf("%s Unidentified websocket data received: %+v", + return fmt.Errorf("%s received unidentified data: %+v", k.Name, response) } } + return nil } @@ -559,37 +581,36 @@ func (k *Kraken) wsProcessSpread(channelData *WebsocketChannelData, data []inter } // wsProcessTrades converts trade data and sends it to the datahandler -func (k *Kraken) wsProcessTrades(channelData *WebsocketChannelData, data []interface{}) { +func (k *Kraken) wsProcessTrades(channelData *WebsocketChannelData, data []interface{}) error { + if !k.IsSaveTradeDataEnabled() { + return nil + } + var trades []trade.Data for i := range data { - trade := data[i].([]interface{}) - timeData, err := strconv.ParseFloat(trade[2].(string), 64) + t, ok := data[i].([]interface{}) + if !ok { + return errors.New("unidentified trade data received") + } + timeData, err := strconv.ParseFloat(t[2].(string), 64) if err != nil { - k.Websocket.DataHandler <- err - return + return err } - price, err := strconv.ParseFloat(trade[0].(string), 64) + price, err := strconv.ParseFloat(t[0].(string), 64) if err != nil { - k.Websocket.DataHandler <- err - return + return err } - amount, err := strconv.ParseFloat(trade[1].(string), 64) + amount, err := strconv.ParseFloat(t[1].(string), 64) if err != nil { - k.Websocket.DataHandler <- err - return + return err } var tSide = order.Buy - if trade[3].(string) == "s" { + if t[3].(string) == "s" { tSide = order.Sell } - var tType = order.Market - if trade[4].(string) == "l" { - tType = order.Limit - } - - k.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ AssetType: asset.Spot, CurrencyPair: channelData.Pair, Exchange: k.Name, @@ -597,9 +618,9 @@ func (k *Kraken) wsProcessTrades(channelData *WebsocketChannelData, data []inter Amount: amount, Timestamp: convert.TimeFromUnixTimestampDecimal(timeData), Side: tSide, - EventType: tType, - } + }) } + return trade.AddTradesToBuffer(k.Name, trades...) } // wsProcessOrderBook determines if the orderbook data is partial or update diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index dac8573b..18dd04ca 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -3,6 +3,7 @@ package kraken import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -514,9 +516,47 @@ func (k *Kraken) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (k *Kraken) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (k *Kraken) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = k.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData []RecentTrades + tradeData, err = k.GetTrades(assetTranslator.LookupCurrency(p.String())) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + side := order.Buy + if tradeData[i].BuyOrSell == "s" { + side = order.Sell + } + resp = append(resp, trade.Data{ + Exchange: k.Name, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Volume, + Timestamp: convert.TimeFromUnixTimestampDecimal(tradeData[i].Time), + }) + } + + err = k.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (k *Kraken) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/lakebtc/lakebtc.go b/exchanges/lakebtc/lakebtc.go index 6279d390..2be15e4a 100644 --- a/exchanges/lakebtc/lakebtc.go +++ b/exchanges/lakebtc/lakebtc.go @@ -141,12 +141,9 @@ func (l *LakeBTC) GetOrderBook(currency string) (Orderbook, error) { } // GetTradeHistory returns the trade history for a given currency pair -func (l *LakeBTC) GetTradeHistory(currency string, start int64) ([]TradeHistory, error) { +func (l *LakeBTC) GetTradeHistory(currency string) ([]TradeHistory, error) { v := url.Values{} v.Set("symbol", strings.ToLower(currency)) - if start != 0 { - v.Set("at", strconv.FormatInt(start, 10)) - } path := fmt.Sprintf("%s/%s?%s", l.API.Endpoints.URL, lakeBTCTrades, v.Encode()) var resp []TradeHistory return resp, l.SendHTTPRequest(path, &resp) diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go index d81f47f2..61ed6241 100644 --- a/exchanges/lakebtc/lakebtc_test.go +++ b/exchanges/lakebtc/lakebtc_test.go @@ -76,7 +76,7 @@ func TestGetOrderBook(t *testing.T) { func TestGetTradeHistory(t *testing.T) { t.Parallel() - _, err := l.GetTradeHistory("BTCUSD", time.Now().Unix()) + _, err := l.GetTradeHistory("BTCUSD") if err != nil { t.Error("GetTradeHistory() error", err) } @@ -451,15 +451,6 @@ func TestWsConn(t *testing.T) { } } -// TestWsTradeProcessing logic test -func TestWsTradeProcessing(t *testing.T) { - json := `{"trades":[{"type":"sell","date":1564985787,"price":"11913.02","amount":"0.49"}]}` - err := l.processTrades(json, "market-btcusd-global") - if err != nil { - t.Error(err) - } -} - // TestWsTickerProcessing logic test func TestWsTickerProcessing(t *testing.T) { json := `{"btcusd":{"low":"10990.05","high":"11966.24","last":"11903.29","volume":"1803.967079","sell":"11912.39","buy":"11902.2"},"btceur":{"low":"9886.87","high":"10732.72","last":"10691.44","volume":"87.994478","sell":"10711.62","buy":"10691.44"},"btchkd":{"low":null,"high":null,"last":"51776.98","volume":null,"sell":"93307.37","buy":"93177.56"},"btcjpy":{"low":"1176039.0","high":"1272246.0","last":"1265680.0","volume":"129.021421","sell":"1266764.0","buy":"1265680.0"},"btcgbp":{"low":"9157.12","high":"9953.43","last":"9941.28","volume":"10.4997","sell":"10007.89","buy":"9941.28"},"btcaud":{"low":"16102.57","high":"17594.22","last":"17548.16","volume":"7.338316","sell":"17616.67","buy":"17549.69"},"btccad":{"low":"14541.69","high":"15834.87","last":"15763.54","volume":"30.480309","sell":"15793.45","buy":"15756.13"},"btcsgd":{"low":"15133.82","high":"16501.62","last":"16455.53","volume":"4.044026","sell":"16484.37","buy":"16462.18"},"btcchf":{"low":"10800.58","high":"11526.24","last":"11526.24","volume":"0.1765","sell":"11675.34","buy":"11632.02"},"btcnzd":{"low":null,"high":null,"last":"8340.98","volume":null,"sell":"18315.49","buy":"18221.37"},"btcngn":{"low":null,"high":null,"last":"600000.0","volume":null,"sell":null,"buy":null},"eurusd":{"low":"1.1088","high":"1.1138","last":"1.1125","volume":"2680.105249","sell":"1.1142","buy":"1.1121"},"gbpusd":{"low":"1.1934","high":"1.1958","last":"1.1934","volume":"1493.923823","sell":"1.1979","buy":"1.1903"},"usdjpy":{"low":"105.26","high":"107.25","last":"106.33","volume":"114490.2179","sell":"106.34","buy":"106.27"},"usdhkd":{"low":null,"high":null,"last":"7.851","volume":null,"sell":"7.8328","buy":"7.8286"},"usdcad":{"low":"1.3225","high":"1.3272","last":"1.3255","volume":"11033.9877","sell":"1.3258","buy":"1.3238"},"usdsgd":{"low":"1.3776","high":"1.3839","last":"1.3838","volume":"2523.75","sell":"1.3838","buy":"1.3819"},"audusd":{"low":"0.6764","high":"0.6853","last":"0.6771","volume":"5442.608321","sell":"0.6782","buy":"0.6762"},"nzdusd":{"low":null,"high":null,"last":"0.6758","volume":null,"sell":"0.6532","buy":"0.6504"},"usdchf":{"low":"0.9838","high":"0.9838","last":"0.9838","volume":"108.3352","sell":"0.9801","buy":"0.9773"},"usdngn":{"low":null,"high":null,"last":"200.0","volume":null,"sell":null,"buy":null},"ethbtc":{"low":"0.0205","high":"0.025","last":"0.0205","volume":null,"sell":"0.03","buy":"0.0194"},"ltcbtc":{"low":null,"high":null,"last":"0.0114","volume":null,"sell":"0.009","buy":"0.0073"},"bchbtc":{"low":null,"high":null,"last":"0.0544","volume":null,"sell":"0.0322","buy":"0.0274"},"xrpbtc":{"low":"0.000042","high":"0.000042","last":"0.000042","volume":null,"sell":"0.000037","buy":"0.000022"},"baceth":{"low":"0.000035","high":"0.000035","last":"0.000035","volume":null,"sell":"0.0015","buy":null}}` @@ -491,3 +482,30 @@ func TestWsOrderbookProcessing(t *testing.T) { t.Error(err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = l.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTCUSD") + if err != nil { + t.Fatal(err) + } + _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Hour*24), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } + if err == nil { + t.Error("expected error") + } +} diff --git a/exchanges/lakebtc/lakebtc_types.go b/exchanges/lakebtc/lakebtc_types.go index 4dde4310..e706156d 100644 --- a/exchanges/lakebtc/lakebtc_types.go +++ b/exchanges/lakebtc/lakebtc_types.go @@ -37,7 +37,7 @@ type TickerResponse struct { // TradeHistory holds trade history data type TradeHistory struct { - Date int64 `json:"data"` + Date int64 `json:"date"` Price float64 `json:"price,string"` Amount float64 `json:"amount,string"` TID int64 `json:"tid"` diff --git a/exchanges/lakebtc/lakebtc_websocket.go b/exchanges/lakebtc/lakebtc_websocket.go index f197ba79..8308d1e6 100644 --- a/exchanges/lakebtc/lakebtc_websocket.go +++ b/exchanges/lakebtc/lakebtc_websocket.go @@ -11,7 +11,6 @@ import ( "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" - "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" @@ -24,10 +23,6 @@ const ( marketGlobalEndpoint = "market-global" marketSubstring = "market-" globalSubstring = "-global" - tickerHighString = "high" - tickerLastString = "last" - tickerLowString = "low" - tickerVolumeString = "volume" wssSchem = "wss" ) @@ -72,10 +67,9 @@ func (l *LakeBTC) listenToEndpoints() error { if err != nil { return fmt.Errorf("%s Websocket Bind error: %s", l.Name, err) } - l.WebsocketConn.Trade, err = l.WebsocketConn.Client.Bind("trades") - if err != nil { - return fmt.Errorf("%s Websocket Bind error: %s", l.Name, err) - } + // LakeBTC does not provide enough trade data to sync to the trade database table + // please use REST until the API is updated + // l.WebsocketConn.Trade, err = l.WebsocketConn.Client.Bind("trades") return nil } @@ -154,15 +148,6 @@ func (l *LakeBTC) wsHandleIncomingData() { if err != nil { l.Websocket.DataHandler <- err } - case data := <-l.WebsocketConn.Trade: - if l.Verbose { - log.Debugf(log.ExchangeSys, - "%v Websocket message received: %v", l.Name, data) - } - err := l.processTrades(data.Data, data.Channel) - if err != nil { - l.Websocket.DataHandler <- err - } case data := <-l.WebsocketConn.Orderbook: if l.Verbose { log.Debugf(log.ExchangeSys, @@ -180,39 +165,6 @@ func (l *LakeBTC) wsHandleIncomingData() { } } -func (l *LakeBTC) processTrades(data, channel string) error { - var tradeData WsTrades - err := json.Unmarshal([]byte(data), &tradeData) - if err != nil { - return err - } - curr, err := l.getCurrencyFromChannel(channel) - if err != nil { - return err - } - - for i := range tradeData.Trades { - tSide, err := order.StringToOrderSide(tradeData.Trades[i].Type) - if err != nil { - l.Websocket.DataHandler <- order.ClassificationError{ - Exchange: l.Name, - Err: err, - } - } - l.Websocket.DataHandler <- stream.TradeData{ - Timestamp: time.Unix(tradeData.Trades[i].Date, 0), - CurrencyPair: curr, - AssetType: asset.Spot, - Exchange: l.Name, - EventType: order.UnknownType, - Price: tradeData.Trades[i].Price, - Amount: tradeData.Trades[i].Amount, - Side: tSide, - } - } - return nil -} - func (l *LakeBTC) processOrderbook(obUpdate, channel string) error { var update WsOrderbookUpdate err := json.Unmarshal([]byte(obUpdate), &update) diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index f582a214..a27a71a1 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -3,6 +3,7 @@ package lakebtc import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -349,9 +351,44 @@ func (l *LakeBTC) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (l *LakeBTC) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (l *LakeBTC) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = l.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + var tradeData []TradeHistory + tradeData, err = l.GetTradeHistory(p.String()) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTS := time.Unix(tradeData[i].Date, 0) + resp = append(resp, trade.Data{ + TID: strconv.FormatInt(tradeData[i].TID, 10), + Exchange: l.Name, + CurrencyPair: p, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTS, + }) + } + + err = l.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (l *LakeBTC) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/lbank/lbank.go b/exchanges/lbank/lbank.go index b1d1c995..46cefd52 100644 --- a/exchanges/lbank/lbank.go +++ b/exchanges/lbank/lbank.go @@ -98,12 +98,16 @@ func (l *Lbank) GetMarketDepths(symbol, size, merge string) (MarketDepthResponse } // GetTrades returns an array of available trades regarding a particular exchange -func (l *Lbank) GetTrades(symbol, size, time string) ([]TradeResponse, error) { +func (l *Lbank) GetTrades(symbol string, limit, time int64) ([]TradeResponse, error) { var g []TradeResponse params := url.Values{} params.Set("symbol", symbol) - params.Set("size", size) - params.Set("time", time) + if limit > 0 { + params.Set("size", strconv.FormatInt(limit, 10)) + } + if time > 0 { + params.Set("time", strconv.FormatInt(time, 10)) + } path := fmt.Sprintf("%s/v%s/%s?%s", l.API.Endpoints.URL, lbankAPIVersion, lbankTrades, params.Encode()) return g, l.SendHTTPRequest(path, &g) } diff --git a/exchanges/lbank/lbank_test.go b/exchanges/lbank/lbank_test.go index 065e4559..b9252744 100644 --- a/exchanges/lbank/lbank_test.go +++ b/exchanges/lbank/lbank_test.go @@ -91,12 +91,11 @@ func TestGetMarketDepths(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := l.GetTrades(testCurrencyPair, "600", - strconv.FormatInt(time.Now().Unix(), 10)) + _, err := l.GetTrades(testCurrencyPair, 600, time.Now().Unix()) if err != nil { t.Error(err) } - a, err := l.GetTrades(testCurrencyPair, "600", "0") + a, err := l.GetTrades(testCurrencyPair, 600, 0) if len(a) != 600 && err != nil { t.Error(err) } @@ -484,3 +483,32 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { }) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testCurrencyPair) + if err != nil { + t.Fatal(err) + } + _, err = l.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString(testCurrencyPair) + if err != nil { + t.Fatal(err) + } + _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil { + t.Error(err) + } + // longer term + _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*60*200), time.Now().Add(-time.Minute*60*199)) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go index 6da8fab4..8c9c2d95 100644 --- a/exchanges/lbank/lbank_wrapper.go +++ b/exchanges/lbank/lbank_wrapper.go @@ -2,6 +2,7 @@ package lbank import ( "fmt" + "sort" "strconv" "strings" "sync" @@ -19,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -326,9 +328,70 @@ func (l *Lbank) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (l *Lbank) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrFunctionNotSupported +// GetRecentTrades returns the most recent trades for a currency and asset +func (l *Lbank) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return l.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (l *Lbank) GetHistoricTrades(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + p, err = l.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + ts := timestampStart + limit := 600 +allTrades: + for { + var tradeData []TradeResponse + tradeData, err = l.GetTrades(p.String(), int64(limit), ts.UnixNano()/int64(time.Millisecond)) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTime := time.Unix(0, tradeData[i].DateMS*int64(time.Millisecond)) + if tradeTime.Before(timestampStart) || tradeTime.After(timestampEnd) { + break allTrades + } + side := order.Buy + if strings.Contains(tradeData[i].Type, "sell") { + side = order.Sell + } + resp = append(resp, trade.Data{ + Exchange: l.Name, + TID: tradeData[i].TID, + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTime, + }) + if i == len(tradeData)-1 { + if ts.Equal(tradeTime) { + // reached end of trades to crawl + break allTrades + } + ts = tradeTime + } + } + if len(tradeData) != limit { + break allTrades + } + } + + err = l.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return trade.FilterTradesByTime(resp, timestampStart, timestampEnd), nil } // SubmitOrder submits a new order @@ -586,7 +649,7 @@ func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]ord } resp.Price = tempResp.Orders[0].Price resp.Amount = tempResp.Orders[0].Amount - resp.Date = time.Unix(tempResp.Orders[0].CreateTime, 9) + resp.Date = time.Unix(tempResp.Orders[0].CreateTime, 0) resp.ExecutedAmount = tempResp.Orders[0].DealAmount resp.RemainingAmount = tempResp.Orders[0].Amount - tempResp.Orders[0].DealAmount resp.Fee, err = l.GetFeeByType(&exchange.FeeBuilder{ @@ -678,7 +741,7 @@ func (l *Lbank) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]ord } resp.Price = tempResp.Orders[x].Price resp.Amount = tempResp.Orders[x].Amount - resp.Date = time.Unix(tempResp.Orders[x].CreateTime, 9) + resp.Date = time.Unix(tempResp.Orders[x].CreateTime, 0) resp.ExecutedAmount = tempResp.Orders[x].DealAmount resp.RemainingAmount = tempResp.Orders[x].Price - tempResp.Orders[x].DealAmount resp.Fee, err = l.GetFeeByType(&exchange.FeeBuilder{ diff --git a/exchanges/localbitcoins/localbitcoins.go b/exchanges/localbitcoins/localbitcoins.go index f86016ff..93e3964b 100644 --- a/exchanges/localbitcoins/localbitcoins.go +++ b/exchanges/localbitcoins/localbitcoins.go @@ -673,7 +673,7 @@ func (l *LocalBitcoins) GetTradableCurrencies() ([]string, error) { // GetTrades returns all closed trades in online buy and online sell categories, // updated every 15 minutes. func (l *LocalBitcoins) GetTrades(currency string, values url.Values) ([]Trade, error) { - path := common.EncodeURLValues(fmt.Sprintf("%s/%s/trades.json", l.API.Endpoints.URL+localbitcoinsAPIBitcoincharts, currency), values) + path := common.EncodeURLValues(fmt.Sprintf("%s%s/trades.json", l.API.Endpoints.URL+localbitcoinsAPIBitcoincharts, currency), values) var result []Trade return result, l.SendHTTPRequest(path, &result) } diff --git a/exchanges/localbitcoins/localbitcoins_test.go b/exchanges/localbitcoins/localbitcoins_test.go index 59328e2a..9f76ce6b 100644 --- a/exchanges/localbitcoins/localbitcoins_test.go +++ b/exchanges/localbitcoins/localbitcoins_test.go @@ -2,6 +2,7 @@ package localbitcoins import ( "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/core" @@ -94,6 +95,13 @@ func setFeeBuilder() *exchange.FeeBuilder { } } +func TestGetTrades(t *testing.T) { + _, err := l.GetTrades("LTC", nil) + if err != nil { + t.Error(err) + } +} + // TestGetFeeByTypeOfflineTradeFee logic test func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { t.Parallel() @@ -399,3 +407,27 @@ func TestGetDepositAddress(t *testing.T) { t.Error("GetDepositAddress() error", err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-LTC") + if err != nil { + t.Fatal(err) + } + _, err = l.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-LTC") + if err != nil { + t.Fatal(err) + } + _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 46d92751..5acc81b9 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "sort" "strconv" "strings" "sync" @@ -21,6 +22,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -284,9 +286,43 @@ func (l *LocalBitcoins) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (l *LocalBitcoins) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (l *LocalBitcoins) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = l.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData []Trade + tradeData, err = l.GetTrades(p.Quote.String(), nil) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + resp = append(resp, trade.Data{ + Exchange: l.Name, + TID: strconv.FormatInt(tradeData[i].TID, 10), + CurrencyPair: p, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: time.Unix(tradeData[i].Date, 0), + }) + } + + err = l.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (l *LocalBitcoins) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/mock/README.md b/exchanges/mock/README.md index 4b0bb5cf..a2f67391 100644 --- a/exchanges/mock/README.md +++ b/exchanges/mock/README.md @@ -1,211 +1,211 @@ -# GoCryptoTrader package Mock - - - - -[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader) -[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE) -[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/mock) -[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master) -[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader) - - -This mock package is part of the GoCryptoTrader codebase. - -## This is still in active development - -You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader). - -Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk) - -## Mock Testing Suite - -## Current Features for mock -+ REST recording service -+ REST mock response server - -### How to enable - -+ Any exchange with mock testing will be enabled by default. This is done using build tags which are highlighted in the examples below via `//+build mock_test_off`. To disable and run live endpoint testing parse `-tags=mock_test_off` as a go test param. - -## Mock test setup - -+ Create two additional test files for the exchange. Examples are below: - -### file one - your_current_exchange_name_live_test.go - -```go -//+build mock_test_off - -// This will build if build tag mock_test_off is parsed and will do live testing -// using all tests in (exchange)_test.go -package your_current_exchange_name - -import ( - "os" - "testing" - "log" - - "github.com/thrasher-corp/gocryptotrader/config" - "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" -) - -var mockTests = false - -func TestMain(m *testing.M) { - cfg := config.GetConfig() - cfg.LoadConfig("../../testdata/configtest.json") - your_current_exchange_nameConfig, err := cfg.GetExchangeConfig("your_current_exchange_name") - if err != nil { - log.Fatal("your_current_exchange_name Setup() init error", err) - } - your_current_exchange_nameConfig.API.AuthenticatedSupport = true - your_current_exchange_nameConfig.API.Credentials.Key = apiKey - your_current_exchange_nameConfig.API.Credentials.Secret = apiSecret - s.SetDefaults() - s.Setup(&your_current_exchange_nameConfig) - log.Printf(sharedtestvalues.LiveTesting, s.Name, s.API.Endpoints.URL) - os.Exit(m.Run()) -} -``` - -### file two - your_current_exchange_name_mock_test.go - -```go -//+build !mock_test_off - -// This will build if build tag mock_test_off is not parsed and will try to mock -// all tests in _test.go -package your_current_exchange_name - -import ( - "os" - "testing" - "log" - - "github.com/thrasher-corp/gocryptotrader/config" - "github.com/thrasher-corp/gocryptotrader/exchanges/mock" - "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" -) - -const mockfile = "../../testdata/http_mock/your_current_exchange_name/your_current_exchange_name.json" - -var mockTests = true - -func TestMain(m *testing.M) { - cfg := config.GetConfig() - cfg.LoadConfig("../../testdata/configtest.json") - your_current_exchange_nameConfig, err := cfg.GetExchangeConfig("your_current_exchange_name") - if err != nil { - log.Fatal("your_current_exchange_name Setup() init error", err) - } - your_current_exchange_nameConfig.API.AuthenticatedSupport = true - your_current_exchange_nameConfig.API.Credentials.Key = apiKey - your_current_exchange_nameConfig.API.Credentials.Secret = apiSecret - s.SetDefaults() - s.Setup(&your_current_exchange_nameConfig) - - serverDetails, newClient, err := mock.NewVCRServer(mockfile) - if err != nil { - log.Fatalf("Mock server error %s", err) - } - - s.HTTPClient = newClient - s.API.Endpoints.URL = serverDetails - - log.Printf(sharedtestvalues.MockTesting, s.Name, s.API.Endpoints.URL) - os.Exit(m.Run()) -} - -``` - -## Mock test storage - -+ Under `testdata/http_mock` create a folder matching the name of your exchange. Then create a JSON file matching the name of your exchange with the following formatting: -``` -{ - "routes": { - } -} -``` - - -## Recording a test result - -+ Once the files `your_current_exchange_name_mock_test.go` and `your_current_exchange_name_live_test.go` along with the JSON file `testdata/http_mock/our_current_exchange_name/our_current_exchange_name.json` are created, go through each individual test function and add - -```go -var s SomeExchange - -func TestDummyTest(t *testing.T) { - s.Verbose = true // This will show you some fancy debug output - s.HTTPRecording = true // This will record the request and response payloads - s.API.Endpoints.URL = apiURL // This will overwrite the current mock url at localhost - s.API.Endpoints.URLSecondary = secondAPIURL // This is only if your API has multiple endpoints - s.HTTPClient = http.DefaultClient // This will ensure that a real HTTPClient is used to record - err := s.SomeExchangeEndpointFunction() - // check error -} -``` - -+ This will store the request and results under the freshly created `testdata/http_mock/your_current_exchange/your_current_exchange.json` - -## Validating - -+ To check if the recording was successful, comment out recording and apiurl changes, then re-run test. - -```go -var s SomeExchange - -func TestDummyTest(t *testing.T) { - s.Verbose = true // This will show you some fancy debug output - // s.HTTPRecording = true // This will record the request and response payloads - // s.API.Endpoints.URL = apiURL // This will overwrite the current mock url at localhost - // s.API.Endpoints.URLSecondary = secondAPIURL // This is only if your API has multiple endpoints - // s.HTTPClient = http.DefaultClient // This will ensure that a real HTTPClient is used to record - err := s.SomeExchangeEndpointFunction() - // check error -} -``` - -+ The payload should be the same. - -## Considerations - -+ Some functions require timestamps. Mock tests _must_ match the same request structure, so `time.Now()` will cause problems for mock testing. - + To address this, use the boolean variable `mockTests` to create a consistent date. An example is below. -``` - startTime := time.Now().Add(-time.Hour * 1) - endTime := time.Now() - if mockTests { - startTime = time.Date(2020, 9, 1, 0, 0, 0, 0, time.UTC) - endTime = time.Date(2020, 9, 2, 0, 0, 0, 0, time.UTC) - } -``` -+ Authenticated endpoints will typically require valid API keys and a signature to run successfully. Authenticated endpoints should be skipped. See an example below -``` - if mockTests { - t.Skip("skipping authenticated function for mock testing") - } -``` - -### Please click GoDocs chevron above to view current GoDoc information for this package - -## Contribution - -Please feel free to submit any pull requests or suggest any desired features to be added. - -When submitting a PR, please abide by our coding guidelines: - -+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). -+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. -+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md). -+ Pull requests need to be based on and opened against the `master` branch. - -## Donations - - - -If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to: - -***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc*** +# GoCryptoTrader package Mock + + + + +[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader) +[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE) +[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/mock) +[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader) + + +This mock package is part of the GoCryptoTrader codebase. + +## This is still in active development + +You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader). + +Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk) + +## Mock Testing Suite + +## Current Features for mock ++ REST recording service ++ REST mock response server + +### How to enable + ++ Any exchange with mock testing will be enabled by default. This is done using build tags which are highlighted in the examples below via `//+build mock_test_off`. To disable and run live endpoint testing parse `-tags=mock_test_off` as a go test param. + +## Mock test setup + ++ Create two additional test files for the exchange. Examples are below: + +### file one - your_current_exchange_name_live_test.go + +```go +//+build mock_test_off + +// This will build if build tag mock_test_off is parsed and will do live testing +// using all tests in (exchange)_test.go +package your_current_exchange_name + +import ( + "os" + "testing" + "log" + + "github.com/thrasher-corp/gocryptotrader/config" + "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" +) + +var mockTests = false + +func TestMain(m *testing.M) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + your_current_exchange_nameConfig, err := cfg.GetExchangeConfig("your_current_exchange_name") + if err != nil { + log.Fatal("your_current_exchange_name Setup() init error", err) + } + your_current_exchange_nameConfig.API.AuthenticatedSupport = true + your_current_exchange_nameConfig.API.Credentials.Key = apiKey + your_current_exchange_nameConfig.API.Credentials.Secret = apiSecret + s.SetDefaults() + s.Setup(&your_current_exchange_nameConfig) + log.Printf(sharedtestvalues.LiveTesting, s.Name, s.API.Endpoints.URL) + os.Exit(m.Run()) +} +``` + +### file two - your_current_exchange_name_mock_test.go + +```go +//+build !mock_test_off + +// This will build if build tag mock_test_off is not parsed and will try to mock +// all tests in _test.go +package your_current_exchange_name + +import ( + "os" + "testing" + "log" + + "github.com/thrasher-corp/gocryptotrader/config" + "github.com/thrasher-corp/gocryptotrader/exchanges/mock" + "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" +) + +const mockfile = "../../testdata/http_mock/your_current_exchange_name/your_current_exchange_name.json" + +var mockTests = true + +func TestMain(m *testing.M) { + cfg := config.GetConfig() + cfg.LoadConfig("../../testdata/configtest.json") + your_current_exchange_nameConfig, err := cfg.GetExchangeConfig("your_current_exchange_name") + if err != nil { + log.Fatal("your_current_exchange_name Setup() init error", err) + } + your_current_exchange_nameConfig.API.AuthenticatedSupport = true + your_current_exchange_nameConfig.API.Credentials.Key = apiKey + your_current_exchange_nameConfig.API.Credentials.Secret = apiSecret + s.SetDefaults() + s.Setup(&your_current_exchange_nameConfig) + + serverDetails, newClient, err := mock.NewVCRServer(mockfile) + if err != nil { + log.Fatalf("Mock server error %s", err) + } + + s.HTTPClient = newClient + s.API.Endpoints.URL = serverDetails + + log.Printf(sharedtestvalues.MockTesting, s.Name, s.API.Endpoints.URL) + os.Exit(m.Run()) +} + +``` + +## Mock test storage + ++ Under `testdata/http_mock` create a folder matching the name of your exchange. Then create a JSON file matching the name of your exchange with the following formatting: +``` +{ + "routes": { + } +} +``` + + +## Recording a test result + ++ Once the files `your_current_exchange_name_mock_test.go` and `your_current_exchange_name_live_test.go` along with the JSON file `testdata/http_mock/our_current_exchange_name/our_current_exchange_name.json` are created, go through each individual test function and add + +```go +var s SomeExchange + +func TestDummyTest(t *testing.T) { + s.Verbose = true // This will show you some fancy debug output + s.HTTPRecording = true // This will record the request and response payloads + s.API.Endpoints.URL = apiURL // This will overwrite the current mock url at localhost + s.API.Endpoints.URLSecondary = secondAPIURL // This is only if your API has multiple endpoints + s.HTTPClient = http.DefaultClient // This will ensure that a real HTTPClient is used to record + err := s.SomeExchangeEndpointFunction() + // check error +} +``` + ++ This will store the request and results under the freshly created `testdata/http_mock/your_current_exchange/your_current_exchange.json` + +## Validating + ++ To check if the recording was successful, comment out recording and apiurl changes, then re-run test. + +```go +var s SomeExchange + +func TestDummyTest(t *testing.T) { + s.Verbose = true // This will show you some fancy debug output + // s.HTTPRecording = true // This will record the request and response payloads + // s.API.Endpoints.URL = apiURL // This will overwrite the current mock url at localhost + // s.API.Endpoints.URLSecondary = secondAPIURL // This is only if your API has multiple endpoints + // s.HTTPClient = http.DefaultClient // This will ensure that a real HTTPClient is used to record + err := s.SomeExchangeEndpointFunction() + // check error +} +``` + ++ The payload should be the same. + +## Considerations + ++ Some functions require timestamps. Mock tests _must_ match the same request structure, so `time.Now()` will cause problems for mock testing. + + To address this, use the boolean variable `mockTests` to create a consistent date. An example is below. +``` + startTime := time.Now().Add(-time.Hour * 1) + endTime := time.Now() + if mockTests { + startTime = time.Date(2020, 9, 1, 0, 0, 0, 0, time.UTC) + endTime = time.Date(2020, 9, 2, 0, 0, 0, 0, time.UTC) + } +``` ++ Authenticated endpoints will typically require valid API keys and a signature to run successfully. Authenticated endpoints should be skipped. See an example below +``` + if mockTests { + t.Skip("skipping authenticated function for mock testing") + } +``` + +### Please click GoDocs chevron above to view current GoDoc information for this package + +## Contribution + +Please feel free to submit any pull requests or suggest any desired features to be added. + +When submitting a PR, please abide by our coding guidelines: + ++ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). ++ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. ++ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md). ++ Pull requests need to be based on and opened against the `master` branch. + +## Donations + + + +If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to: + +***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc*** diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go index 3f3a9768..cbe28c89 100644 --- a/exchanges/okcoin/okcoin_test.go +++ b/exchanges/okcoin/okcoin_test.go @@ -1118,3 +1118,27 @@ func TestGetHistoricCandlesExtended(t *testing.T) { t.Fatal("unexpected result") } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-USDT") + if err != nil { + t.Fatal(err) + } + _, err = o.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC-USDT") + if err != nil { + t.Fatal(err) + } + _, err = o.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index f27d0922..091d5331 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -2,6 +2,8 @@ package okcoin import ( "errors" + "fmt" + "sort" "sync" "time" @@ -13,10 +15,12 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/okgroup" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -459,3 +463,49 @@ func (o *OKCoin) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, st ret.SortCandlesByTimestamp(false) return ret, nil } + +// GetRecentTrades returns the most recent trades for a currency and asset +func (o *OKCoin) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = o.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + switch assetType { + case asset.Spot: + var tradeData []okgroup.GetSpotFilledOrdersInformationResponse + tradeData, err = o.GetSpotFilledOrdersInformation(okgroup.GetSpotFilledOrdersInformationRequest{ + InstrumentID: p.String(), + }) + if err != nil { + return nil, err + } + for i := range tradeData { + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: o.Name, + TID: tradeData[i].TradeID, + CurrencyPair: p, + Side: side, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Size, + Timestamp: tradeData[i].Timestamp, + }) + } + default: + return nil, fmt.Errorf("%s asset type %v unsupported", o.Name, assetType) + } + err = o.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} diff --git a/exchanges/okex/okex.go b/exchanges/okex/okex.go index ca94ce00..33af40ba 100644 --- a/exchanges/okex/okex.go +++ b/exchanges/okex/okex.go @@ -156,7 +156,7 @@ func (o *OKEX) GetFuturesTokenInfoForCurrency(instrumentID string) (resp okgroup // The whole book will be returned for one request. Websocket is recommended here. func (o *OKEX) GetFuturesFilledOrder(request okgroup.GetFuturesFilledOrderRequest) (resp []okgroup.GetFuturesFilledOrdersResponse, _ error) { requestURL := fmt.Sprintf("%v/%v/%v%v", okgroup.OKGroupInstruments, request.InstrumentID, okgroup.OKGroupTrades, okgroup.FormatParameters(request)) - return resp, o.SendHTTPRequest(http.MethodGet, okGroupFuturesSubsection, requestURL, nil, &resp, true) + return resp, o.SendHTTPRequest(http.MethodGet, okGroupFuturesSubsection, requestURL, nil, &resp, false) } // GetFuturesHoldAmount Get the number of futures with hold. diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index dadacbd3..aa29c5b3 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -1033,7 +1033,9 @@ func TestGetFuturesFilledOrder(t *testing.T) { _, err := o.GetFuturesFilledOrder(okgroup.GetFuturesFilledOrderRequest{ InstrumentID: getFutureInstrumentID(), }) - testStandardErrorHandling(t, err) + if err != nil { + t.Error(err) + } } // TestGetFuturesHoldAmount API endpoint test @@ -2132,3 +2134,27 @@ func TestStringToOrderStatus(t *testing.T) { } } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("NEO-USDT_SWAP") + if err != nil { + t.Fatal(err) + } + _, err = o.GetRecentTrades(currencyPair, asset.PerpetualSwap) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("NEO-USDT_SWAP") + if err != nil { + t.Fatal(err) + } + _, err = o.GetHistoricTrades(currencyPair, asset.PerpetualSwap, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/okex/okex_wrapper.go b/exchanges/okex/okex_wrapper.go index bd5d7784..4585aa49 100644 --- a/exchanges/okex/okex_wrapper.go +++ b/exchanges/okex/okex_wrapper.go @@ -3,6 +3,7 @@ package okex import ( "errors" "fmt" + "sort" "strings" "sync" "time" @@ -15,10 +16,12 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/okgroup" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -691,3 +694,98 @@ func (o *OKEX) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, star ret.SortCandlesByTimestamp(false) return ret, nil } + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (o *OKEX) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = o.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + var side order.Side + switch assetType { + case asset.Spot: + var tradeData []okgroup.GetSpotFilledOrdersInformationResponse + tradeData, err = o.GetSpotFilledOrdersInformation(okgroup.GetSpotFilledOrdersInformationRequest{ + InstrumentID: p.String(), + }) + if err != nil { + return nil, err + } + for i := range tradeData { + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: o.Name, + TID: tradeData[i].TradeID, + CurrencyPair: p, + Side: side, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Size, + Timestamp: tradeData[i].Timestamp, + }) + } + case asset.Futures: + var tradeData []okgroup.GetFuturesFilledOrdersResponse + tradeData, err = o.GetFuturesFilledOrder(okgroup.GetFuturesFilledOrderRequest{ + InstrumentID: p.String(), + }) + if err != nil { + return nil, err + } + for i := range tradeData { + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: o.Name, + TID: tradeData[i].TradeID, + CurrencyPair: p, + Side: side, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Qty, + Timestamp: tradeData[i].Timestamp, + }) + } + case asset.PerpetualSwap: + var tradeData []okgroup.GetSwapFilledOrdersDataResponse + tradeData, err = o.GetSwapFilledOrdersData(&okgroup.GetSwapFilledOrdersDataRequest{ + InstrumentID: p.String(), + }) + if err != nil { + return nil, err + } + for i := range tradeData { + side, err = order.StringToOrderSide(tradeData[i].Side) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: o.Name, + TID: tradeData[i].TradeID, + CurrencyPair: p, + Side: side, + AssetType: assetType, + Price: tradeData[i].Price, + Amount: tradeData[i].Size, + Timestamp: tradeData[i].Timestamp, + }) + } + default: + return nil, fmt.Errorf("%s asset type %v unsupported", o.Name, assetType) + } + + err = o.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} diff --git a/exchanges/okgroup/okgroup_types.go b/exchanges/okgroup/okgroup_types.go index 66d6a611..2242e094 100644 --- a/exchanges/okgroup/okgroup_types.go +++ b/exchanges/okgroup/okgroup_types.go @@ -323,9 +323,9 @@ type GetSpotFilledOrdersInformationRequest struct { // GetSpotFilledOrdersInformationResponse response data for GetSpotFilledOrdersInformation type GetSpotFilledOrdersInformationResponse struct { - Price string `json:"price"` + Price float64 `json:"price,string"` Side string `json:"side"` - Size string `json:"size"` + Size float64 `json:"size,string"` Timestamp time.Time `json:"timestamp"` TradeID string `json:"trade_id"` } @@ -719,7 +719,7 @@ type GetFuturesFilledOrderRequest struct { // GetFuturesFilledOrdersResponse response data for GetFuturesFilledOrders type GetFuturesFilledOrdersResponse struct { Price float64 `json:"price,string"` - Qty int64 `json:"qty,string"` + Qty float64 `json:"qty,string"` Side string `json:"side"` Timestamp time.Time `json:"timestamp"` TradeID string `json:"trade_id"` diff --git a/exchanges/okgroup/okgroup_websocket.go b/exchanges/okgroup/okgroup_websocket.go index 9e97877b..f271914a 100644 --- a/exchanges/okgroup/okgroup_websocket.go +++ b/exchanges/okgroup/okgroup_websocket.go @@ -21,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -146,7 +147,6 @@ const ( allowableIterations = 25 delimiterColon = ":" delimiterDash = "-" - delimiterUnderscore = "_" maxConnByteLen = 4096 ) @@ -410,7 +410,7 @@ func (o *OKGroup) wsProcessTickers(respRaw []byte) error { case asset.Futures, asset.PerpetualSwap: c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], - delimiterUnderscore) + currency.UnderscoreDelimiter) default: c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash) } @@ -446,6 +446,9 @@ func (o *OKGroup) wsProcessTickers(respRaw []byte) error { // wsProcessTrades converts trade data and sends it to the datahandler func (o *OKGroup) wsProcessTrades(respRaw []byte) error { + if !o.IsSaveTradeDataEnabled() { + return nil + } var response WebsocketTradeResponse err := json.Unmarshal(respRaw, &response) if err != nil { @@ -453,6 +456,7 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error { } a := o.GetAssetTypeFromTableName(response.Table) + var trades []trade.Data for i := range response.Data { f := strings.Split(response.Data[i].InstrumentID, delimiterDash) @@ -461,7 +465,7 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error { case asset.Futures, asset.PerpetualSwap: c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], - delimiterUnderscore) + currency.UnderscoreDelimiter) default: c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash) } @@ -478,8 +482,7 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error { if response.Data[i].Quantity != 0 { amount = response.Data[i].Quantity } - - o.Websocket.DataHandler <- stream.TradeData{ + trades = append(trades, trade.Data{ Amount: amount, AssetType: o.GetAssetTypeFromTableName(response.Table), CurrencyPair: c, @@ -487,9 +490,10 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error { Price: response.Data[i].Price, Side: tSide, Timestamp: response.Data[i].Timestamp, - } + TID: response.Data[i].TradeID, + }) } - return nil + return trade.AddTradesToBuffer(o.Name, trades...) } // wsProcessCandles converts candle data and sends it to the data handler @@ -509,7 +513,7 @@ func (o *OKGroup) wsProcessCandles(respRaw []byte) error { case asset.Futures, asset.PerpetualSwap: c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], - delimiterUnderscore) + currency.UnderscoreDelimiter) default: c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash) } @@ -575,7 +579,7 @@ func (o *OKGroup) WsProcessOrderBook(respRaw []byte) error { case asset.Futures, asset.PerpetualSwap: c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], - delimiterUnderscore) + currency.UnderscoreDelimiter) default: c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash) } diff --git a/exchanges/okgroup/okgroup_wrapper.go b/exchanges/okgroup/okgroup_wrapper.go index a7f22f81..8b568001 100644 --- a/exchanges/okgroup/okgroup_wrapper.go +++ b/exchanges/okgroup/okgroup_wrapper.go @@ -16,6 +16,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -260,11 +261,6 @@ func (o *OKGroup) GetFundingHistory() (resp []exchange.FundHistory, err error) { return resp, err } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (o *OKGroup) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented -} - // SubmitOrder submits a new order func (o *OKGroup) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) { err := s.Validate() @@ -569,3 +565,8 @@ func (o *OKGroup) ValidateCredentials() error { _, err := o.UpdateAccountInfo() return o.CheckTransientError(err) } + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (o *OKGroup) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported +} diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 9163eacb..6da136b4 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -156,16 +156,16 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, e } // GetTradeHistory returns trades history from poloniex -func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]TradeHistory, error) { +func (p *Poloniex) GetTradeHistory(currencyPair string, start, end int64) ([]TradeHistory, error) { vals := url.Values{} vals.Set("currencyPair", currencyPair) - if start != "" { - vals.Set("start", start) + if start > 0 { + vals.Set("start", strconv.FormatInt(start, 10)) } - if end != "" { - vals.Set("end", end) + if end > 0 { + vals.Set("end", strconv.FormatInt(end, 10)) } var resp []TradeHistory diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go index 2b72693a..d5b8d18b 100644 --- a/exchanges/poloniex/poloniex_test.go +++ b/exchanges/poloniex/poloniex_test.go @@ -57,7 +57,7 @@ func TestGetOrderbook(t *testing.T) { func TestGetTradeHistory(t *testing.T) { t.Parallel() - _, err := p.GetTradeHistory("BTC_XMR", "", "") + _, err := p.GetTradeHistory("BTC_XMR", 0, 0) if err != nil { t.Error("Test faild - Poloniex GetTradeHistory() error", err) } @@ -499,7 +499,7 @@ func TestWsPriceAggregateOrderbook(t *testing.T) { if err != nil { t.Error(err) } - pressXToJSON := []byte(`[148,827987828,[["i",{"currencyPair":"BTC_ETH","orderBook":[{"0.02311264":"2.20557811","0.02311600":"84.08160000","0.02312999":"8.64968477","0.02313000":"1.04012298","0.02313832":"8.65139901","0.02314389":"8.17308984","0.02314390":"85.00000000","0.02315000":"0.22107450","0.02316698":"3.58606790","0.02316699":"18.28000000","0.02316700":"3.38902934","0.02317926":"60.56000000","0.02317927":"0.00593568","0.02322065":"586.54000000","0.02322448":"43.65239848","0.02322500":"0.22107450","0.02325301":"0.24886762","0.02326884":"0.86320742","0.02328311":"0.08824715","0.02328536":"0.04303557","0.02328537":"0.31420536","0.02328584":"0.01000000","0.02328626":"0.05000000","0.02328870":"0.30372277","0.02329327":"0.05000000","0.02329517":"0.00590632","0.02329681":"0.05000000","0.02329695":"0.05000000","0.02329828":"0.05000000","0.02329836":"0.75160000","0.02329850":"0.05609507","0.02329867":"0.00870000","0.02330000":"1.87647637","0.02330070":"0.03410191","0.02330381":"0.05000000","0.02331083":"0.16078678","0.02331243":"0.02000000","0.02331556":"0.05770631","0.02331557":"0.05770630","0.02331558":"0.05770630","0.02332181":"0.03040000","0.02332235":"0.21717356","0.02333128":"0.04081941","0.02333191":"0.00996007","0.02333333":"0.76706001","0.02333377":"0.01000000","0.02333753":"0.26851522","0.02334247":"1.00000000","0.02334475":"0.08619536","0.02334476":"0.08619532","0.02334514":"0.08619249","0.02334515":"0.08619246","0.02334563":"0.08618886","0.02334615":"0.08618506","0.02334999":"82.25709323","0.02335000":"2.00920859","0.02335954":"0.59849633","0.02336562":"0.05151537","0.02337443":"3.24458234","0.02337500":"0.22107450","0.02337945":"0.00887856","0.02339740":"0.00570128","0.02339836":"0.75170000","0.02339850":"0.05609507","0.02340000":"8.35534261","0.02340222":"0.50014040","0.02341165":"0.00587696","0.02341488":"0.02229647","0.02342000":"0.03000000","0.02342803":"0.51603525","0.02343000":"1.99700000","0.02344057":"0.20000000","0.02344501":"0.50009878","0.02344864":"0.04468562","0.02345000":"1.22607450","0.02346052":"0.45364582","0.02348918":"0.01138875","0.02349000":"6.01963602","0.02349836":"0.75180000","0.02349850":"0.05609507","0.02350000":"23.38752043","0.02350019":"0.02363135","0.02350369":"0.04379185","0.02350587":"0.55500002","0.02350588":"0.55500001","0.02352500":"0.22107450","0.02352801":"0.01736539","0.02352871":"0.00584760","0.02353636":"0.59849633","0.02354000":"0.08984535","0.02354023":"0.01419758","0.02354800":"0.05000000","0.02355000":"1.00000000","0.02356542":"0.01268000","0.02356600":"0.04133829","0.02357107":"0.03040000","0.02357377":"5.53105357","0.02357945":"2.00000000","0.02358000":"0.05512230","0.02359836":"0.75190000","0.02359850":"0.05609507","0.02359902":"0.30000000","0.02360000":"5.59692724","0.02360795":"0.01313436","0.02361184":"0.74575578","0.02361788":"0.10951236","0.02363000":"1.00000000","0.02363690":"0.02437918","0.02364090":"4.23191724","0.02364200":"0.00563594","0.02364296":"175.56000000","0.02364636":"0.00581874","0.02365000":"1.00500000","0.02365298":"3.02119704","0.02365532":"50.00000000","0.02367945":"1.00000000","0.02369836":"0.75200000","0.02370000":"0.80891942","0.02370060":"0.01000000","0.02370409":"3.95849091","0.02371452":"0.59849633","0.02371605":"0.10000000","0.02372441":"1.00000000","0.02374515":"0.07733034","0.02375000":"11.13820000","0.02375489":"0.10000000","0.02376460":"0.00578988","0.02377976":"0.25726394","0.02379400":"3.49253617","0.02379850":"0.05609507","0.02380000":"25.12680676","0.02381381":"0.28349641","0.02381560":"5.21495064","0.02382270":"0.82483502","0.02382554":"17.00801738","0.02382885":"0.00884413","0.02383610":"5.61081721","0.02383690":"0.02379185","0.02384024":"0.01824364","0.02384265":"3.78056119","0.02386942":"0.01332000","0.02388343":"0.00576100","0.02388489":"0.10000000","0.02389000":"10.00000000","0.02389403":"0.59849633","0.02389775":"0.04000000","0.02390000":"0.33845599","0.02390161":"0.01320844","0.02393000":"5.00000000","0.02395000":"0.00500000","0.02395905":"0.10000000","0.02396145":"0.45364582","0.02396728":"0.25000000","0.02397000":"0.20000000","0.02397945":"1.32526449","0.02398100":"0.07150300","0.02398900":"0.04962855","0.02399000":"0.10000000","0.02399641":"0.75010000","0.02399850":"0.05609507","0.02399890":"0.10000000","0.02399923":"0.03234736","0.02399999":"0.01390173","0.02400000":"78.68354747","0.02400285":"0.00573214","0.02400743":"0.27244440","0.02401560":"1.09209339","0.02402070":"0.02871320","0.02402330":"0.01420000","0.02403549":"1.15760251","0.02404000":"0.00512238","0.02406526":"0.06435309","0.02407490":"0.59849633","0.02407511":"0.22916250","0.02408001":"0.10000000","0.02408900":"0.10000000","0.02409434":"0.55695311","0.02409560":"0.90000000","0.02409641":"0.75020000","0.02410000":"10.00829876","0.02411745":"0.00720165","0.02412287":"0.00570376","0.02412560":"1.00000000","0.02413000":"0.05095410","0.02413424":"0.01313436","0.02415200":"0.00549829","0.02415247":"0.01916181","0.02415900":"9.00000000","0.02417109":"0.01400000","0.02418080":"0.10000000","0.02418900":"0.02391850","0.02419132":"0.99850000","0.02419641":"0.75030000","0.02420000":"4.98736614","0.02420510":"5.00000000","0.02421887":"0.00454382","0.02424000":"0.46055829","0.02424349":"0.00567538","0.02424504":"4.03787835","0.02424849":"0.61837624","0.02425714":"0.59849633","0.02426315":"0.01000000","0.02428900":"0.10000000","0.02429641":"0.75040000","0.02429981":"0.29848383","0.02430000":"0.44132634","0.02430922":"0.11114354","0.02431247":"59.20000000","0.02432377":"0.17599103","0.02434712":"0.75000000","0.02434824":"0.00720165","0.02436376":"6.53422874","0.02436471":"0.00564700","0.02436630":"0.00503621","0.02437654":"0.02373257","0.02438900":"0.02239185","0.02438910":"0.00504710","0.02439641":"0.75050000","0.02440000":"10.00409837","0.02440820":"7.89038111","0.02444076":"0.59849633","0.02446013":"0.22682291","0.02446281":"0.02011990","0.02447201":"50.00000000","0.02447277":"0.01468000","0.02448900":"0.10000000","0.02449641":"0.75060000","0.02449993":"0.03203089","0.02450000":"7.90099804","0.02451172":"0.06941288","0.02452000":"0.00494192","0.02452220":"0.13664099","0.02453205":"6.00000000","0.02454430":"61.92378648","0.02458900":"0.02292401","0.02459641":"0.75070000","0.02460000":"0.15813010","0.02461943":"0.31185184","0.02462577":"0.59849633","0.02463340":"0.00473821","0.02465000":"0.08113000","0.02468900":"0.10000000","0.02469000":"0.10000000","0.02469442":"0.00720165","0.02469641":"0.75080000","0.02470000":"7.71371820","0.02475857":"0.16516852","0.02476952":"1.00000000","0.02477337":"0.00500000","0.02477444":"0.01540000","0.02477504":"0.02111791","0.02477724":"0.06258849","0.02479573":"0.31347716","0.02479641":"0.75090000","0.02480000":"10.00000000","0.02480748":"0.23814629","0.02481218":"0.59849633","0.02482560":"1.00000000","0.02482784":"0.01228842","0.02483000":"0.01500000","0.02486093":"4.00000000","0.02486501":"0.50000000","0.02487660":"0.90000000","0.02488749":"0.00409844","0.02488900":"0.10000000","0.02488977":"0.04000000","0.02489000":"0.35163940","0.02489641":"0.75100000","0.02490000":"10.58814327","0.02491000":"0.00608537","0.02491500":"1.71477436","0.02491966":"0.00409315","0.02493728":"0.25000000","0.02495701":"0.00721241","0.02495881":"0.45364582","0.02496508":"0.45122312","0.02499000":"1.29455628","0.02499036":"0.69792104","0.02499641":"0.75110000","0.02499999":"0.04948379","0.02500000":"119.42337109","0.02500069":"0.11974446","0.02503742":"0.00998500","0.02505233":"8.00000000","0.02506435":"0.45600000","0.02507612":"0.01620000","0.02508727":"0.02215584","0.02508900":"0.10000000","0.02509641":"0.75120000","0.02511088":"1.81386399","0.02514830":"0.01500000","0.02515188":"2.81540025","0.02515200":"0.50014866","0.02515600":"0.00720165","0.02515800":"0.05000000","0.02515987":"0.12949064","0.02517000":"1.18940537","0.02518080":"0.10000000","0.02519641":"0.75130000","0.02520000":"20.80000000","0.02520548":"0.50029134","0.02522000":"1.94462357","0.02524800":"0.05000000","0.02529641":"0.75140000","0.02529925":"0.13992865","0.02530000":"10.11581028","0.02530177":"0.32847591","0.02535134":"2.99550001","0.02535408":"0.01000000","0.02535746":"0.28697654","0.02535752":"5.51788977","0.02536270":"0.01000000","0.02536962":"0.01000000","0.02538011":"0.01700000","0.02538758":"0.07045847","0.02539136":"0.49999222","0.02539641":"0.75150000","0.02539761":"0.02327362","0.02540000":"21.00393701","0.02540549":"0.12890839","0.02543942":"0.25000000","0.02544346":"0.06078266","0.02545749":"0.45364582","0.02547368":"0.01000000","0.02548000":"0.00493328","0.02549641":"0.75160000","0.02550000":"44.09979658","0.02552638":"0.30000000","0.02553003":"0.16000000","0.02554581":"0.20000000","0.02555080":"0.31508157","0.02555555":"0.22235762","0.02557201":"50.00000000","0.02559641":"0.75170000","0.02559999":"0.01956367","0.02560000":"1.05956590","0.02560417":"6.91427454","0.02566000":"0.12766398","0.02566176":"0.76304697","0.02568001":"20.00000000","0.02568179":"0.01784000","0.02569100":"3.03013591","0.02569641":"0.75180000","0.02569756":"0.21625244","0.02570000":"1.80000000","0.02570984":"0.02443131","0.02575872":"0.11591332","0.02575989":"0.09399662","0.02579641":"0.75190000","0.02580000":"0.06392453","0.02581814":"0.34347967","0.02582554":"20.00000000","0.02583260":"0.03004038","0.02583580":"0.41763784","0.02585000":"0.03000000","0.02585200":"4.82562511","0.02588000":"699.37000014","0.02588800":"1.00000000","0.02588977":"0.02000000","0.02589000":"0.05000000","0.02589380":"0.05000000","0.02589641":"0.75200000","0.02590000":"6.97837447","0.02591420":"0.11270626","0.02592439":"0.25000010","0.02593801":"0.50000000","0.02595842":"0.22682291","0.02597578":"0.22916250","0.02598346":"0.01876000","0.02599000":"0.10000000","0.02599900":"10.00000000","0.02600000":"38.19875434","0.02601926":"0.01270000","0.02602019":"0.02566884","0.02605141":"0.10000000","0.02606000":"1.00000000","0.02607021":"0.00458189","0.02607063":"0.10958793","0.02607609":"0.02527763","0.02610000":"0.01149426","0.02610165":"0.12733523","0.02611000":"1.33000000","0.02613128":"0.40718911","0.02615000":"1.00000000","0.02617537":"0.18914366","0.02617538":"0.15131493","0.02618080":"0.10000000","0.02618300":"0.96184394","0.02620000":"0.00381680","0.02622799":"0.10655588","0.02628746":"0.01968000","0.02629875":"0.14067708","0.02630000":"0.01140685","0.02633241":"0.02738542","0.02634505":"0.35848783","0.02635000":"0.12319035","0.02635297":"1.50038712","0.02636015":"0.05000000","0.02636679":"0.04266747","0.02638631":"0.10360773","0.02638975":"0.82414691","0.02640000":"0.15000000","0.02640731":"0.75010000","0.02641900":"2.14880491","0.02642590":"0.09617133","0.02644800":"0.05000000","0.02645710":"0.45364582","0.02650000":"3.31519613","0.02650731":"0.75020000","0.02651000":"0.03000000","0.02651179":"0.08054606","0.02652890":"0.04995500","0.02654305":"0.03774159","0.02654558":"0.10074115","0.02656273":"0.00535411","0.02657668":"0.14871273","0.02658913":"0.02068000","0.02659482":"0.09842772","0.02660000":"1.16527949","0.02660731":"0.75030000","0.02663150":"0.00468029","0.02668000":"0.18300000","0.02668421":"0.01000000","0.02668612":"3.99400001","0.02669733":"0.01427223","0.02670000":"0.50000000","0.02670581":"0.09795387","0.02670731":"0.75040000","0.02675000":"1.33289836","0.02677997":"17.00000000","0.02679710":"0.09126439","0.02680000":"0.05609507","0.02680731":"0.75050000","0.02685210":"5.00000000","0.02686060":"0.55695311","0.02686100":"5.00000000","0.02686701":"0.09524371","0.02688271":"0.37349961","0.02688977":"0.02000000","0.02689081":"0.02172000","0.02689886":"0.05000000","0.02690000":"0.50743495","0.02690322":"0.11596188","0.02690584":"0.83413998","0.02690731":"0.75060000","0.02692108":"1.00000000","0.02692439":"0.25000000","0.02695579":"0.90729164","0.02699700":"0.41586666","0.02700000":"63.13214997","0.02700731":"0.75070000","0.02701000":"2.00000000","0.02701926":"0.01276691","0.02702533":"0.10000000","0.02703308":"0.09274765","0.02705141":"0.10000000","0.02705454":"0.05600000","0.02706001":"0.15000000","0.02710000":"2.00000000","0.02710428":"0.05562809","0.02710731":"0.75080000","0.02711000":"1.00000000","0.02712000":"1.51496323","0.02712401":"0.02212063","0.02715000":"0.50000000","0.02717000":"0.03000000","0.02718081":"0.10000000","0.02719248":"0.02280000","0.02720000":"5.50000000","0.02720409":"0.09045269","0.02720731":"0.75090000","0.02723000":"1.99700001","0.02723758":"0.12391620","0.02725000":"1.00000000","0.02725675":"3.21390363","0.02727509":"0.99650250","0.02728000":"9.00000000","0.02730000":"0.04459353","0.02730002":"0.02498750","0.02730731":"0.75100000","0.02732000":"0.05000000","0.02736458":"0.00370277","0.02736830":"0.08795008","0.02739000":"1.00000000","0.02740731":"0.75110000","0.02743134":"0.38851429","0.02749648":"0.02392000","0.02749900":"0.84902282","0.02750000":"0.72623627","0.02750731":"0.75120000","0.02752000":"1.00000000","0.02753026":"0.05625351","0.02753349":"0.08551670","0.02760724":"1.55058834","0.02760731":"0.75130000","0.02767000":"1.00000000","0.02769894":"0.75010000","0.02769969":"0.08315065","0.02770000":"0.50722022","0.02770731":"0.75140000","0.02775311":"0.25149783","0.02777583":"0.10000000","0.02777777":"0.32903348","0.02779815":"0.02512000","0.02779894":"0.75020000","0.02780002":"0.02488750","0.02780731":"0.75150000","0.02781000":"1.00000000","0.02782067":"0.20002484","0.02784380":"0.05000000","0.02785000":"0.03000000","0.02786690":"0.08085006","0.02788800":"1.00000000","0.02788977":"0.02000000","0.02789473":"0.01000000","0.02789520":"7.58055660","0.02789894":"0.75030000","0.02790000":"8.05234495","0.02790731":"0.75160000","0.02792439":"0.25000000","0.02793779":"6.00441683","0.02793899":"33.12016500","0.02794172":"1.20858953","0.02795000":"1.00000000","0.02796308":"0.73084727","0.02796459":"0.49960000","0.02797515":"0.00361034","0.02799117":"0.40353124","0.02799894":"0.75040000","0.02799900":"3.00000000","0.02800000":"91.71497999","0.02800731":"0.75170000","0.02801195":"1.00000000","0.02801918":"0.00998501","0.02803511":"0.07861313","0.02808672":"5.04047013","0.02808700":"1.00000000","0.02809894":"0.75050000","0.02809983":"0.02640000","0.02810000":"0.01087841","0.02810731":"0.75180000","0.02811179":"0.00880000","0.02817226":"2.29316776","0.02818081":"0.10000000","0.02819894":"0.75060000","0.02820000":"0.23581929","0.02820275":"0.01997195","0.02820731":"0.75190000","0.02821247":"0.07666791","0.02823000":"1.00000000","0.02824360":"0.04995501","0.02826560":"0.00518056","0.02826942":"11.30521404","0.02827980":"0.00148286","0.02829894":"0.75070000","0.02830000":"0.14997662","0.02830133":"0.65626553","0.02830235":"0.06492216","0.02830307":"0.05100000","0.02830731":"0.75200000","0.02831000":"2.00000000","0.02832000":"2.00000000","0.02832800":"0.11380644","0.02833591":"0.13225196","0.02833917":"0.11376158","0.02834500":"1.00000000","0.02835000":"0.01562299","0.02837000":"1.00000000","0.02838000":"0.02554615","0.02838540":"0.00399579","0.02838685":"0.07465868","0.02839894":"0.75080000","0.02840000":"0.41236886","0.02840150":"0.02772000","0.02840794":"0.11549974","0.02845000":"2.00000000","0.02846913":"0.11407423","0.02847935":"0.11392010","0.02849894":"0.75090000","0.02849999":"0.50000000","0.02850000":"1.55519463","0.02850865":"0.11329579","0.02855257":"5.19446106","0.02855820":"0.07259305","0.02856242":"0.41854937","0.02856341":"0.01000000","0.02857000":"1.00000000","0.02859000":"2.00000000","0.02859894":"0.75100000","0.02860000":"2.10000000","0.02862340":"0.14683131","0.02863022":"0.09036925","0.02867000":"1.00000000","0.02869894":"0.75110000","0.02870000":"0.53560677","0.02870550":"0.02908000","0.02873560":"2.00000000","0.02873561":"0.11327961","0.02873888":"0.07079680","0.02875179":"0.11523373","0.02877000":"1.00000000","0.02877652":"0.57993828","0.02877699":"3.99459870","0.02878800":"0.05000000","0.02879894":"1.22074954","0.02880000":"0.10000000","0.02884380":"0.05000000","0.02887000":"1.00000000","0.02888080":"2.00000000","0.02888977":"0.02000000","0.02889894":"0.75130000","0.02890000":"0.00692042","0.02891235":"0.06883801","0.02892439":"0.25000000","0.02893170":"0.22000000","0.02897000":"1.00000000","0.02898000":"0.10000000","0.02898970":"2.00000000","0.02898999":"1.50850000","0.02899200":"5.00000000","0.02899894":"0.75140000","0.02899990":"0.50000000","0.02899999":"0.00348276","0.02900000":"39.58254996","0.02900717":"0.03092000","0.02900801":"4.98392820","0.02905233":"11.76652676","0.02907000":"1.00000000","0.02908687":"0.06693342","0.02909894":"0.75150000","0.02910000":"0.30000000","0.02910526":"0.01000000","0.02913127":"0.50019306","0.02914533":"0.43356789","0.02917000":"1.00000000","0.02919894":"0.75160000","0.02920000":"0.05988966","0.02922500":"0.49550000","0.02923000":"0.71185556","0.02926245":"0.06508152","0.02927000":"1.00000000","0.02929530":"0.11106687","0.02929570":"5.64837395","0.02929894":"0.75170000","0.02930000":"0.00682594","0.02930922":"0.08279308","0.02933246":"0.11027274","0.02933306":"0.05752906","0.02934800":"0.04009406","0.02935000":"63.62280623","0.02938990":"133.85550640","0.02939487":"4.00000000","0.02939894":"0.75180000","0.02940000":"0.32840000","0.02945540":"2.00000000","0.02948388":"0.01034125","0.02949000":"1.00000000","0.02949038":"0.08062332","0.02949894":"0.75190000","0.02949900":"0.90000000","0.02949999":"0.50000000","0.02950000":"2.33681337","0.02950271":"0.02995501","0.02955390":"2.00000000","0.02956349":"150.00000000","0.02959000":"1.00000000","0.02959300":"0.10894162","0.02959894":"0.75200000","0.02960000":"0.19968002","0.02960486":"0.16589051","0.02960566":"0.02020101","0.02961260":"0.50000000","0.02961500":"0.98026530","0.02961880":"0.00500000","0.02962200":"0.09990000","0.02965240":"2.00000000","0.02966600":"0.04800000","0.02966839":"0.07839266","0.02968001":"20.00000000","0.02970000":"0.70673401","0.02973501":"1.00000000","0.02974014":"0.44858586","0.02975020":"2.00000000","0.02978270":"0.20066926","0.02980000":"0.27215573","0.02980810":"0.10000000","0.02981000":"20.00000000","0.02984089":"0.40078848","0.02984980":"0.00013407","0.02986037":"0.07656776","0.02987900":"2.00000000","0.02988000":"0.10000000","0.02988512":"0.00337960","0.02988594":"0.64503100","0.02988686":"0.18500000","0.02988800":"1.00000000","0.02988949":"0.25310759","0.02988977":"0.02000000","0.02989569":"0.52000000","0.02990000":"13.50000000","0.02991031":"0.10812416","0.02991430":"0.00437040","0.02991550":"0.40000000","0.02992550":"0.20112207","0.02992883":"0.27109250","0.02993063":"0.40022317","0.02993967":"7.11081548","0.02994000":"0.49000000","0.02995000":"1.00000000","0.02995536":"1.00330087","0.02996003":"0.45353476","0.02996687":"0.40139117","0.02997000":"2.00000000","0.02998197":"0.16239264","0.02998700":"0.00435313","0.02998777":"0.10898917","0.02999065":"0.40138676","0.02999999":"1.74055624","0.03000000":"204.40711041","0.03000839":"0.10841111","0.03001150":"0.00438126","0.03004122":"0.07038661","0.03004493":"0.07456115","0.03004507":"1.99700000","0.03005700":"2.00000000","0.03009002":"0.01536906","0.03010000":"0.00664452","0.03014000":"0.05783801","0.03014800":"2.00000000","0.03015000":"5.00000000","0.03016868":"0.05600000","0.03019064":"0.00548600","0.03023850":"2.00000000","0.03025000":"0.20000000","0.03026405":"1.05472646","0.03029999":"20.48401000","0.03030000":"3.00000000","0.03030329":"2.00000000","0.03031578":"0.01000000","0.03034709":"0.46360209","0.03035698":"3.95196084","0.03036380":"2.00000000","0.03038459":"0.01005016","0.03040000":"3.06044136","0.03040131":"0.40454980","0.03042200":"2.00000000","0.03049999":"0.50000000","0.03050000":"2.62245738","0.03051200":"2.00000000","0.03056576":"0.10700000","0.03056698":"0.07257089","0.03056995":"0.00613604","0.03057450":"0.01534726","0.03057615":"0.00330322","0.03060000":"3.65000000","0.03060290":"2.00000000","0.03062601":"0.17131452","0.03062970":"0.00443008","0.03063950":"0.00443356","0.03064900":"0.00442141","0.03066351":"0.12922011","0.03067651":"0.25064543","0.03070000":"1.75867885","0.03070531":"0.99700004","0.03073199":"1.17671349","0.03073370":"0.01000000","0.03074500":"0.01530000","0.03074501":"0.09000000","0.03074890":"2.00000000","0.03076000":"0.00342490","0.03079999":"0.49920000","0.03080000":"0.12280000","0.03080140":"0.99910000","0.03080810":"0.10000000","0.03081335":"2.02942486","0.03081481":"0.12384400","0.03082000":"0.20000000","0.03084100":"2.00000000","0.03084707":"0.00365249","0.03086000":"0.20000000","0.03086384":"0.00364827","0.03086720":"0.00464773","0.03087453":"3.68300000","0.03088977":"0.02000000","0.03089880":"0.01063939","0.03090000":"0.51522250","0.03092290":"0.00463763","0.03093210":"0.02000000","0.03093400":"2.00000000","0.03094158":"0.06871377","0.03094219":"0.25000000","0.03095000":"1.00000000","0.03095073":"0.07725004","0.03096000":"0.36800788","0.03096642":"0.47861524","0.03097890":"0.00463111","0.03098000":"1.00000000","0.03099999":"0.39968000","0.03100000":"14.94840935","0.03102700":"2.00000000","0.03103756":"0.41352670","0.03104960":"0.00060044","0.03105000":"0.20616528","0.03107020":"0.00463812","0.03108081":"0.10000000","0.03109000":"0.06900000","0.03109467":"0.04980511","0.03110000":"11.27708559","0.03110070":"0.00465742","0.03112600":"0.10700240","0.03112835":"0.06681262","0.03113529":"0.02058114","0.03115955":"0.03500000","0.03116042":"0.02345474","0.03118518":"0.12384400","0.03119500":"2.00000000","0.03120000":"10.05000000","0.03120900":"2.00000000","0.03126300":"0.15492489","0.03127726":"0.99920002","0.03129622":"0.09980000","0.03130000":"0.50638978","0.03131625":"0.06496407","0.03133130":"0.90000000","0.03134500":"1.00000000","0.03135297":"0.01800000","0.03135764":"0.04866540","0.03136500":"2.00000000","0.03137037":"0.12384400","0.03137979":"16.00573953","0.03139048":"0.24431985","0.03139667":"0.08981716","0.03139997":"0.16754240","0.03139999":"0.49920000","0.03141500":"2.00000000","0.03145988":"0.88123247","0.03149000":"2.00000000","0.03150000":"1.22818054","0.03150528":"0.06316666","0.03151001":"0.27172975","0.03152100":"2.00000000","0.03152277":"0.03419886","0.03152392":"0.00348941","0.03152631":"0.01000000","0.03152978":"0.01800000","0.03153951":"2.98500001","0.03155550":"1.38000000","0.03155555":"0.12384400","0.03155793":"0.23429190","0.03157392":"0.18637608","0.03159000":"2.00000000","0.03159014":"0.05000000","0.03159606":"0.00357958","0.03159839":"0.49362427","0.03159999":"0.50000000","0.03160000":"1.49722784","0.03161350":"2.00000000","0.03161434":"0.41120580","0.03162551":"4.31104421","0.03163630":"0.03231663","0.03169546":"0.06141898","0.03170000":"1.56499106","0.03170600":"2.00000000","0.03173377":"0.00500000","0.03174074":"0.12384400","0.03174900":"0.01600000","0.03177260":"0.00454190","0.03179850":"2.00000000","0.03179999":"0.49920001","0.03180000":"0.07508364","0.03184000":"0.22548655","0.03188677":"0.05971966","0.03188977":"0.02000000","0.03189100":"2.00000000","0.03189540":"11.00000000","0.03189820":"0.00452968","0.03190000":"0.18948191","0.03191814":"6.14826113","0.03192592":"0.12384400","0.03192669":"0.53391317","0.03194000":"0.01620029","0.03195000":"9.00000000","0.03197270":"0.00454983","0.03198350":"2.00000000","0.03198585":"0.01837025","0.03199791":"0.02296281","0.03199999":"0.50000000","0.03200000":"40.46331921","0.03200077":"0.02101911","0.03200150":"0.00453696","0.03201389":"0.01681528","0.03201621":"0.02307399","0.03203007":"11.64489377","0.03203119":"0.02884249","0.03205119":"0.04105294","0.03206000":"0.08022936","0.03206680":"0.00455929","0.03207600":"2.00000000","0.03207925":"0.05806735","0.03208081":"0.10000000","0.03209626":"6.62407577","0.03210000":"0.12393053","0.03210400":"0.35648705","0.03211111":"0.12384400","0.03212990":"0.00455220","0.03214950":"0.01621173","0.03215000":"3.00000000","0.03215019":"4.88998999","0.03216850":"2.00000000","0.03217200":"3.00000000","0.03217677":"0.06262125","0.03218543":"0.00313806","0.03220000":"1.15948191","0.03224326":"0.50862791","0.03226100":"2.00000000","0.03226124":"0.06245728","0.03226999":"0.04992500","0.03227288":"0.05646076","0.03229629":"0.12384400","0.03229999":"0.99920002","0.03230000":"0.13016174","0.03231500":"0.10181232","0.03232350":"1.00000000","0.03233200":"9.00000000","0.03235301":"1.22645902","0.03235873":"0.01950000","0.03236400":"0.03784381","0.03237000":"1.17551999","0.03237773":"0.00500000","0.03240000":"0.05440053","0.03242358":"0.44391054","0.03247000":"0.00998500","0.03247139":"0.81743961","0.03247236":"0.05494257","0.03248003":"0.10000000","0.03248148":"0.12384400","0.03248480":"1.00000000","0.03249609":"0.05130784","0.03249999":"0.50000000","0.03250000":"2.72776223","0.03250010":"1.91242999","0.03250500":"0.01986860","0.03253072":"0.00455415","0.03254820":"0.04995500","0.03255000":"9.21692308","0.03257791":"100.00000000","0.03258731":"0.01950000","0.03260000":"0.07273198","0.03261434":"0.32202101","0.03261500":"0.93167959","0.03264610":"1.00000000","0.03265490":"0.10000000","0.03266666":"0.12384400","0.03266837":"0.05338501","0.03268001":"20.00000000","0.03270000":"0.86165430","0.03272512":"2.00000000","0.03273000":"0.87709918","0.03273420":"0.00410021","0.03273609":"1.81400310","0.03273684":"0.01000000","0.03277002":"0.04045133","0.03278000":"0.10000000","0.03279210":"0.01896881","0.03279999":"0.50000000","0.03280000":"0.06100000","0.03280275":"0.05080496","0.03280740":"1.00000000","0.03282238":"0.05000000","0.03282725":"0.06000000","0.03285050":"0.03775729","0.03285185":"0.12384400","0.03286557":"0.05187160","0.03287750":"0.00409271","0.03288900":"0.00304068","0.03288977":"0.02000000","0.03290000":"2.25113663","0.03290129":"0.52362474","0.03292100":"0.02000000","0.03295590":"0.01598209","0.03295922":"74.72829286","0.03296870":"1.00000000","0.03298068":"0.28000000","0.03299000":"0.05201528","0.03299999":"0.50306061","0.03300000":"35.78867286","0.03303703":"0.12384400","0.03306395":"0.05040110","0.03310000":"0.19984000","0.03313000":"1.00000000","0.03315000":"0.09507699","0.03315150":"0.01700000","0.03317500":"0.50000000","0.03320501":"0.04512530","0.03322061":"1.00000000","0.03322222":"0.12384400","0.03323208":"0.12257900","0.03326353":"0.04897228","0.03327773":"0.00400000","0.03328500":"0.00478411","0.03328505":"0.03540625","0.03329319":"0.03627504","0.03329700":"1.00000000","0.03329999":"0.50000000","0.03330000":"1.22047166","0.03332083":"0.01841126","0.03332449":"1.15173328","0.03332521":"0.90334769","0.03333004":"2.00348384","0.03333333":"0.82705092","0.03335000":"0.09985000","0.03336380":"2.00000000","0.03340000":"0.11300000","0.03340740":"0.12384400","0.03342498":"0.00500000","0.03345330":"0.00470040","0.03345689":"1.12500000","0.03346400":"1.00000000","0.03346432":"0.04758397","0.03349000":"4.49493001","0.03349999":"0.50000000","0.03350000":"3.53000000","0.03350980":"0.00472970","0.03353397":"2.99550001","0.03353511":"0.45503231","0.03354840":"0.00473430","0.03357275":"0.53861336","0.03358170":"0.00489105","0.03359259":"0.12384400","0.03360000":"0.50000000","0.03360001":"0.08566423","0.03363000":"1.00000000","0.03365324":"0.22706239","0.03366600":"0.02400000","0.03370000":"0.60593472","0.03370469":"0.06845782","0.03370650":"0.04538200","0.03377777":"0.12384400","0.03379999":"0.50000000","0.03380000":"1.10000000","0.03381000":"0.47870875","0.03381673":"0.05000000","0.03384200":"5.00000000","0.03385030":"0.05556334","0.03385502":"0.00305281","0.03387940":"0.00298116","0.03388977":"0.02000000","0.03389000":"0.16400000","0.03390000":"3.13000000","0.03392800":"0.59940000","0.03394441":"0.03733329","0.03394736":"0.01000000","0.03396296":"0.12384400","0.03397000":"1.00000000","0.03398711":"3.00000000","0.03399990":"3.35194511","0.03399999":"1.00000000","0.03400000":"103.12544213","0.03402165":"0.49850000","0.03403141":"0.07437993","0.03404000":"1.00000000","0.03407040":"0.00833380","0.03407645":"0.00681959","0.03408010":"0.01859400","0.03410000":"2.74420534","0.03411000":"0.06843481","0.03414000":"1.00000000","0.03414814":"0.12384400","0.03420000":"0.50000000","0.03420650":"0.04402000","0.03422061":"1.00000000","0.03422161":"0.22389564","0.03425000":"12.51471917","0.03425615":"0.30000000","0.03425791":"0.55359219","0.03426000":"1.07230130","0.03426051":"0.27813022","0.03427309":"0.47364847","0.03427551":"0.04291725","0.03430000":"1.19342189","0.03433333":"0.12384400","0.03436310":"0.06737000","0.03440000":"4.36000000","0.03442000":"0.94450000","0.03443001":"0.77764291","0.03444431":"0.03586522","0.03448000":"1.00000000","0.03449999":"0.54820793","0.03450000":"3.66531584","0.03450004":"0.12063340","0.03450413":"0.05019924","0.03450921":"0.00650506","0.03451851":"0.12384400","0.03453047":"11.98400003","0.03458010":"0.01779194","0.03460000":"75.49777013","0.03462001":"0.51385904","0.03465000":"0.48559718","0.03465500":"1.00000000","0.03468001":"20.00000000","0.03470000":"50.80000000","0.03470279":"0.28830000","0.03470370":"0.12384400","0.03473200":"0.10000000","0.03475578":"2.12049382","0.03480000":"52.30277541","0.03482600":"1.00301438","0.03484501":"0.00289854","0.03486280":"0.03368778","0.03486500":"6.72163862","0.03487500":"0.10000000","0.03487564":"1.87792834","0.03488888":"0.12384400","0.03490000":"5.94332531","0.03490440":"0.38668244","0.03491020":"0.32855150","0.03493000":"0.00445894","0.03494255":"0.93574136","0.03495000":"0.07500000","0.03495687":"0.00944049","0.03495706":"0.56855993","0.03499044":"0.03695204","0.03499990":"1.06302051","0.03499999":"1.00288572","0.03500000":"149.70992406","0.03501549":"0.12361385","0.03501621":"8.28383943","0.03506639":"0.06427397","0.03506796":"0.31900000","0.03507407":"0.12384400","0.03510000":"0.53490666","0.03511000":"15.00000000","0.03513718":"30.27310778","0.03514009":"25.55638417","0.03514800":"0.01000000","0.03515789":"0.01000000","0.03517540":"1.00000000","0.03518100":"14.30644802","0.03520000":"1.10187552","0.03522001":"0.40000000","0.03522061":"1.00000000","0.03523500":"0.04317220","0.03525925":"0.12384400","0.03530000":"3.55722198","0.03534000":"0.13345133","0.03535130":"1.00000000","0.03536000":"0.30215324","0.03536575":"0.92341756","0.03538110":"0.00296607","0.03538604":"0.04376510","0.03540000":"0.06286459","0.03542000":"0.03036359","0.03542480":"1.31418970","0.03544444":"0.12384400","0.03545035":"0.39923857","0.03550000":"3.53980589","0.03550873":"9.96644629","0.03551000":"0.00295324","0.03552000":"10.02973326","0.03552012":"0.06600000","0.03555000":"0.10000000","0.03555800":"0.01000000","0.03560000":"0.20000000","0.03560019":"0.39434889","0.03561154":"0.05427161","0.03562259":"0.51000000","0.03562962":"0.12384400","0.03566000":"0.02897366","0.03566252":"0.00560812","0.03566979":"9.99200001","0.03567047":"0.58351462","0.03569206":"0.02270530","0.03570000":"0.46332624","0.03574388":"0.02822155","0.03577777":"0.22399978","0.03579706":"25.00000000","0.03580000":"0.20000000","0.03581481":"0.12384400","0.03582555":"0.30000000","0.03584000":"0.18601190","0.03585000":"2.67631495","0.03587001":"8.97530639","0.03588220":"0.82119673","0.03588600":"0.05215000","0.03588977":"0.02000000","0.03590000":"0.54457308","0.03590010":"0.00289746","0.03594409":"0.34000000","0.03594511":"0.25053082","0.03595800":"0.04990000","0.03596410":"0.27805506","0.03596597":"2.50509172","0.03596649":"0.00312074","0.03598717":"3.44132754","0.03599000":"1.00000000","0.03599500":"0.04282398","0.03599995":"1.00000000","0.03600000":"15.09450067","0.03600531":"0.01198948","0.03601745":"0.01198545","0.03605701":"0.05611134","0.03607004":"0.01000000","0.03610000":"0.91242654","0.03614469":"0.00845878","0.03615017":"0.05000000","0.03622001":"0.10000000","0.03622061":"1.00000000","0.03629431":"0.08392500","0.03630000":"170.01772058","0.03633000":"0.10000000","0.03635000":"0.00282971","0.03635800":"0.04995000","0.03636842":"0.01000000","0.03639844":"0.59845482","0.03650000":"2035.65768694","0.03651000":"0.00287157","0.03653469":"9.00000000","0.03656444":"0.50000000","0.03657000":"0.00301970","0.03666000":"0.02300000","0.03668487":"0.03000000","0.03670000":"0.58650531","0.03675001":"0.16582457","0.03676000":"0.18135655","0.03678010":"0.08799400","0.03680000":"0.25000000","0.03681000":"0.00277876","0.03682814":"0.48500000","0.03684575":"14.09748290","0.03685859":"0.00832072","0.03688977":"0.02000000","0.03690000":"2.06183461","0.03691000":"0.00283759","0.03691339":"0.01169454","0.03694501":"0.11540885","0.03699900":"0.30000000","0.03699990":"0.00878938","0.03699999":"0.17183290","0.03700000":"41.28064656","0.03701112":"0.62000000","0.03701358":"1.00000000","0.03710000":"5.89532661","0.03712000":"0.42070003","0.03714127":"0.61337888","0.03720000":"9.92210094","0.03722001":"0.10000000","0.03722061":"1.00000000","0.03723000":"0.10000000","0.03723062":"0.11100000","0.03725000":"0.03183039","0.03730000":"1.46255813","0.03732000":"0.20000000","0.03736500":"0.50997335","0.03737500":"0.30938000","0.03738990":"0.07500000","0.03740000":"0.10100000","0.03745282":"0.50000000","0.03750000":"6.65595028","0.03750873":"6.16878466","0.03752638":"1.00000000","0.03753950":"0.00532772","0.03754890":"0.62397475","0.03755379":"0.08567735","0.03757791":"100.00000000","0.03757894":"0.01000000","0.03760000":"1.01000000","0.03760474":"0.02000000","0.03760869":"0.75996023","0.03763120":"2.00000000","0.03765000":"0.35111988","0.03769277":"0.04111557","0.03770000":"0.03986000","0.03775020":"0.00276985","0.03777548":"0.03154002","0.03780000":"1.49970419","0.03780033":"0.11941955","0.03783670":"0.02767829","0.03786890":"0.10425924","0.03789775":"0.02000000","0.03790000":"0.50000000","0.03792122":"1.00000000","0.03795485":"0.30560000","0.03799133":"5.06359526","0.03800000":"142.91727240","0.03800125":"2.95272043","0.03800502":"0.49920000","0.03801000":"0.00844914","0.03801570":"0.01000000","0.03804650":"0.08000000","0.03805000":"2.90777010","0.03809440":"6.00000000","0.03810000":"0.51049869","0.03812356":"0.04286954","0.03815000":"5.97810497","0.03820000":"5.88999071","0.03822001":"0.10000000","0.03822061":"1.00000000","0.03822983":"14.87000000","0.03823450":"0.14988002","0.03826777":"0.03000000","0.03827495":"0.51422232","0.03828003":"1.00000000","0.03828505":"0.25024163","0.03830000":"10.13054830","0.03830939":"0.00760000","0.03833257":"1.00000000","0.03833820":"0.33908658","0.03834000":"1.00000000","0.03834265":"0.10141571","0.03835373":"9.45664547","0.03838990":"0.03771627","0.03839500":"0.12406458","0.03839710":"18.00000000","0.03840000":"3.27000000","0.03840042":"2.90813410","0.03841000":"3.39349335","0.03844327":"0.01122914","0.03845282":"0.50000000","0.03850000":"6.64053767","0.03851400":"10.37885951","0.03854303":"0.20000000","0.03856811":"0.03085757","0.03858835":"0.45200000","0.03860000":"0.06932995","0.03860150":"0.00279446","0.03865000":"0.61183255","0.03867545":"4.00000000","0.03869928":"0.10998380","0.03870000":"0.15000000","0.03871851":"0.07693840","0.03875969":"0.54514010","0.03877888":"0.79297796","0.03878947":"0.01000000","0.03880000":"0.16389000","0.03886500":"0.50000000","0.03887001":"0.06645618","0.03887970":"4.96504761","0.03888800":"0.60251253","0.03890000":"2.11028278","0.03895000":"0.00631900","0.03895500":"1.00000000","0.03897755":"0.02000000","0.03898442":"0.50000000","0.03899999":"0.47495977","0.03900000":"50.40324017","0.03901000":"3.00000000","0.03908100":"0.81684814","0.03909735":"1.00000000","0.03911000":"0.62332022","0.03911110":"2.07258465","0.03912501":"0.00288099","0.03920000":"0.10000000","0.03921541":"0.20500000","0.03921920":"0.20960000","0.03922001":"0.10000000","0.03922061":"1.00000000","0.03927994":"0.10000000","0.03930000":"2.15262515","0.03931500":"0.03196885","0.03934500":"1.00000000","0.03938990":"0.05228373","0.03945282":"0.50000000","0.03945594":"2.67086607","0.03950000":"40.57220235","0.03951526":"0.00506133","0.03955499":"0.05606743","0.03964000":"0.00283097","0.03964807":"0.00283039","0.03966297":"0.58153855","0.03966600":"0.03000000","0.03966812":"0.43674244","0.03968001":"20.00000000","0.03969000":"8.00641027","0.03970000":"0.01007557","0.03974094":"3.31898897","0.03975143":"0.04764533","0.03978110":"0.05958000","0.03978526":"0.36345210","0.03980000":"21.00000000","0.03985000":"0.00627370","0.03985103":"0.22820876","0.03986400":"0.44197171","0.03986500":"10.03386429","0.03987984":"0.00536700","0.03988800":"0.50000000","0.03988977":"0.02000000","0.03990000":"0.57436424","0.03990787":"0.02749400","0.03993949":"0.00430848","0.03994316":"0.00259213","0.03994501":"1.00000000","0.03995152":"5.33338744","0.03995500":"1.00000000","0.03996000":"0.00280830","0.03998000":"0.16358762","0.03998548":"0.41415159","0.03999000":"1.90963042","0.03999900":"0.26577503","0.03999999":"0.00252500","0.04000000":"262.65472968","0.04000001":"25.09504848","0.04000002":"0.60206640","0.04005502":"0.05000000","0.04007262":"3.10027546","0.04007501":"0.00452357","0.04007816":"0.92581596","0.04008000":"0.00429871","0.04010000":"0.09430000","0.04013000":"0.00254794","0.04017000":"0.00512898","0.04020000":"0.08097802","0.04021017":"0.10262700","0.04021516":"0.02931100","0.04021518":"0.00405800","0.04022018":"0.00305300","0.04023019":"0.25724700","0.04024020":"0.17792500","0.04024027":"0.03685425","0.04024048":"0.60311100","0.04025952":"0.05654701","0.04026523":"0.05436699","0.04027170":"1.00000000","0.04027994":"0.10000000","0.04028012":"0.01000000","0.04028124":"0.01057700","0.04028221":"0.03099500","0.04028224":"0.02707100","0.04029331":"1.00000000","0.04030000":"0.20600000","0.04032154":"0.25000000","0.04032527":"0.01360000","0.04032529":"0.05755100","0.04033000":"1.21777790","0.04033029":"0.00745400","0.04033530":"0.13691500","0.04034471":"0.11814700","0.04034971":"0.02909000","0.04035267":"0.01327300","0.04036200":"2.16882840","0.04036531":"0.01792700","0.04039035":"0.01521800","0.04040000":"5.68243519","0.04040036":"0.08636300","0.04040535":"0.01822500","0.04041000":"0.00264520","0.04041037":"0.00371300","0.04042000":"0.00492048","0.04042038":"0.01900400","0.04043262":"0.02493467","0.04045542":"0.09954300","0.04047000":"0.00614794","0.04050000":"2.01452262","0.04051277":"0.03825360","0.04051548":"0.01499800","0.04052000":"0.00463484","0.04052048":"0.07156000","0.04054303":"0.10000000","0.04055000":"0.03606129","0.04056801":"14.02351003","0.04057330":"0.04968884","0.04057500":"0.75000000","0.04059000":"0.00461939","0.04059010":"0.00714177","0.04060000":"0.04995000","0.04061115":"2.24560296","0.04062000":"0.00492012","0.04064000":"0.00459322","0.04066600":"0.03000000","0.04068400":"0.05690620","0.04069000":"0.00481954","0.04070000":"0.10467619","0.04070010":"0.10000000","0.04073000":"0.00477823","0.04073953":"1.16341069","0.04075000":"0.00275385","0.04080000":"0.05579365","0.04082000":"0.00584018","0.04083836":"10.00000000","0.04084139":"0.03786356","0.04086000":"0.00476264","0.04086680":"0.00600000","0.04087000":"0.00473351","0.04088518":"0.15925331","0.04089000":"0.00603607","0.04095000":"0.00485765","0.04097000":"0.00482279","0.04099000":"0.00481520","0.04099500":"0.02114349","0.04099950":"0.00999000","0.04100000":"90.49987653","0.04103000":"0.00479142","0.04103726":"0.20000000","0.04104000":"0.25471758","0.04105000":"0.00483853","0.04106000":"0.00479912","0.04108500":"6.58288790","0.04110000":"3.89891824","0.04110815":"4.69309065","0.04113288":"0.00243358","0.04117000":"0.00464300","0.04120000":"11.30000000","0.04122000":"0.00901005","0.04122001":"0.04709793","0.04123634":"0.00388243","0.04127170":"1.00000000","0.04127994":"0.10000000","0.04130000":"0.00968524","0.04133687":"0.10000000","0.04135001":"0.02000000","0.04140000":"0.09651772","0.04141000":"0.00529806","0.04143592":"0.66400000","0.04144000":"0.00535747","0.04147353":"0.05777503","0.04150000":"1.55389277","0.04151870":"0.07305173","0.04155000":"0.01029603","0.04155110":"12.14738210","0.04156952":"0.03463708","0.04158400":"2.00000000","0.04158999":"0.07235500","0.04159002":"0.11996800","0.04159014":"0.06881586","0.04159501":"0.00985694","0.04160000":"0.20541076","0.04161631":"0.00347226","0.04163000":"0.00564181","0.04166000":"0.00573682","0.04170000":"1.00000000","0.04172000":"0.24029300","0.04175000":"0.15000000","0.04176911":"0.00267063","0.04180000":"0.34030767","0.04181000":"0.49221200","0.04187000":"0.00561758","0.04188518":"0.20000000","0.04189644":"0.07056179","0.04189775":"0.02000000","0.04189999":"0.20000000","0.04190000":"0.04995000","0.04190456":"0.24657238","0.04191706":"0.00266292","0.04192277":"0.03696701","0.04196000":"0.00564954","0.04197561":"0.00264413","0.04200000":"40.83636553","0.04202000":"0.02997000","0.04203726":"0.20000000","0.04205044":"5.17629599","0.04210000":"0.00950119","0.04212999":"0.99950000","0.04213060":"0.42108427","0.04214000":"0.00602497","0.04215000":"0.00602746","0.04215139":"0.03590102","0.04216000":"0.00438466","0.04217000":"0.00599074","0.04220000":"0.25694682","0.04221000":"0.15183316","0.04222001":"0.32840000","0.04223000":"0.00594816","0.04225119":"0.10000000","0.04227170":"1.00000000","0.04230000":"0.12997000","0.04232000":"0.00586094","0.04232001":"0.03000000","0.04233000":"0.00433633","0.04234500":"1.00000000","0.04234637":"7.42155222","0.04237000":"0.00576154","0.04237600":"13.19954408","0.04248540":"1.93059722","0.04250000":"1.97750000","0.04251762":"0.02154667","0.04253951":"7.00000000","0.04257500":"0.51187289","0.04262000":"0.15642109","0.04264500":"13.30696071","0.04264562":"0.08903327","0.04268540":"0.00235000","0.04275000":"0.00266310","0.04276521":"0.00720165","0.04278000":"1.23431400","0.04279000":"0.00431358","0.04280000":"0.08840000","0.04280501":"5.00000000","0.04281587":"11.67791288","0.04285001":"0.00351925","0.04287952":"0.02572755","0.04288286":"0.01006661","0.04288518":"0.10010272","0.04290000":"0.53130001","0.04291213":"0.01005975","0.04293000":"0.00618382","0.04293318":"0.24066483","0.04294000":"0.00616972","0.04294890":"0.12082001","0.04298213":"2.99358081","0.04299000":"0.02975875","0.04299990":"0.50000000","0.04299999":"0.00234884","0.04300000":"51.68620095","0.04301764":"9.36181311","0.04302000":"0.00615043","0.04303000":"0.00599452","0.04303726":"0.20000000","0.04304000":"0.14600000","0.04305000":"0.00611895","0.04308999":"0.05405090","0.04309781":"0.21707959","0.04310869":"2.00000000","0.04311110":"0.50971287","0.04312000":"0.00588898","0.04313007":"0.00874874","0.04315000":"0.00593309","0.04318000":"0.00426272","0.04319503":"4.27395281","0.04322135":"0.46650524","0.04324739":"0.09155089","0.04325000":"0.00555610","0.04325010":"1.14821566","0.04326854":"0.00232000","0.04327170":"0.80000000","0.04330000":"0.00551464","0.04334000":"0.00541327","0.04336000":"0.00557347","0.04339070":"2.83872959","0.04340000":"152.72836484","0.04344000":"0.00524405","0.04345583":"0.24149649","0.04346000":"0.11938289","0.04350000":"1.75000000","0.04350275":"0.39175704","0.04350967":"0.02966281","0.04353000":"0.00424783","0.04355010":"3.06855044","0.04355250":"0.99900000","0.04356000":"0.15304561","0.04356695":"2.53238883","0.04357008":"2.69114180","0.04359000":"0.00266293","0.04360000":"4.70183486","0.04360929":"1.79373271","0.04362000":"0.00539013","0.04363000":"0.00540146","0.04364000":"0.00573105","0.04365000":"0.00575250","0.04367000":"0.00573514","0.04367476":"0.00231254","0.04368001":"20.00000000","0.04369000":"0.00552536","0.04370000":"0.01495187","0.04374000":"0.00576489","0.04374960":"1.20239223","0.04375000":"0.00431223","0.04376000":"0.00538453","0.04377000":"1.00425007","0.04378000":"0.00572569","0.04379000":"0.00553573","0.04380000":"0.00540016","0.04382000":"0.00560844","0.04384500":"1.25572435","0.04387690":"0.07194705","0.04389000":"0.00425595","0.04389444":"0.19074018","0.04389775":"0.02000000","0.04390000":"0.17234000","0.04392187":"0.51780021","0.04395000":"0.00544224","0.04398000":"0.00556427","0.04399000":"0.00547927","0.04400000":"14.77235748","0.04403726":"0.20000000","0.04405181":"1.22580338","0.04407571":"0.49800000","0.04410000":"0.08570000","0.04410001":"0.24260000","0.04412228":"11.51172610","0.04413000":"0.00672367","0.04416000":"0.22644400","0.04418952":"0.03397538","0.04420377":"0.01000000","0.04426499":"0.26834838","0.04426854":"0.00226000","0.04427170":"0.80000000","0.04427994":"0.10000000","0.04429000":"0.00671702","0.04429393":"0.49900000","0.04440000":"0.10163433","0.04450000":"1.50898877","0.04453475":"0.01133946","0.04454383":"0.04500000","0.04456000":"0.00557594","0.04462000":"0.00559911","0.04466600":"0.03000000","0.04469000":"0.00541561","0.04472000":"0.00553695","0.04477000":"0.00548803","0.04477272":"111.67512011","0.04479329":"33.93179783","0.04480000":"0.50544745","0.04490000":"1.30387816","0.04490973":"1.00000000","0.04493000":"0.00651896","0.04494000":"0.00656694","0.04496000":"0.00655056","0.04497000":"2.50334908","0.04497661":"0.08000000","0.04498000":"0.00649353","0.04499999":"0.00244444","0.04500000":"50.76650060","0.04503768":"0.00258794","0.04510046":"0.03594967","0.04515000":"0.11790900","0.04525000":"0.00651953","0.04526854":"0.00221000","0.04527170":"0.80000000","0.04528385":"0.00483799","0.04530000":"0.00883003","0.04532000":"0.00662040","0.04534148":"0.00310398","0.04535000":"0.00641503","0.04537501":"0.35000000","0.04539000":"0.00657631","0.04540000":"0.08320000","0.04544001":"0.00649194","0.04549952":"0.03794177","0.04550000":"1.51266087","0.04557000":"0.00652518","0.04559000":"0.25634340","0.04560000":"0.00646346","0.04563800":"0.11987370","0.04565000":"0.00648532","0.04565973":"9.02687975","0.04568001":"20.00000000","0.04572000":"0.00645935","0.04574000":"0.00227572","0.04579000":"0.60430172","0.04587262":"1.26683478","0.04589775":"0.02000000","0.04590000":"1.00000000","0.04590020":"1.00000000","0.04598899":"0.29584445","0.04599094":"0.00260920","0.04600000":"8.27575330","0.04607000":"0.00390278","0.04610000":"0.00867679","0.04610799":"0.20749839","0.04625010":"0.05498233","0.04626854":"0.00217000","0.04627994":"0.10000000","0.04629338":"2.73010126","0.04640000":"0.21551724","0.04646499":"0.04657911","0.04650000":"1.01500000","0.04654440":"0.50000000","0.04658014":"1.05821384","0.04660503":"1.09539473","0.04665010":"10.00000001","0.04670000":"0.50500000","0.04671065":"0.18617842","0.04680000":"0.08080000","0.04687362":"0.12811675","0.04690000":"0.00852879","0.04693000":"0.01413893","0.04697000":"0.04504425","0.04700000":"13.76893819","0.04702001":"24.32266633","0.04704500":"0.15000000","0.04711190":"0.02235105","0.04720000":"1.00000000","0.04720170":"0.30968276","0.04725000":"0.22882595","0.04726499":"0.26834838","0.04726854":"0.00212000","0.04735801":"0.00278570","0.04745900":"0.00898652","0.04747019":"0.02191354","0.04750000":"5.06552640","0.04750058":"1.54591811","0.04750059":"7.19672456","0.04753000":"0.01115027","0.04757791":"99.00000000","0.04768001":"20.00000000","0.04770000":"0.00838575","0.04774104":"1.00122607","0.04780000":"1.08563357","0.04789775":"0.02000000","0.04790000":"1.60000000","0.04791240":"36.11112151","0.04797854":"0.00861690","0.04798083":"0.30000000","0.04799999":"0.00210417","0.04800000":"13.32205328","0.04807571":"0.50000000","0.04810000":"0.07860000","0.04822995":"2.08441498","0.04824000":"0.47703241","0.04826854":"0.00208000","0.04827519":"0.00211735","0.04830000":"1.71959797","0.04832921":"0.03986890","0.04839072":"0.00240969","0.04839764":"5.45361901","0.04844000":"0.00229770","0.04848000":"8.54119545","0.04850000":"1.00824743","0.04852957":"0.07826151","0.04862286":"0.43950000","0.04868001":"20.00000000","0.04870148":"45.86231136","0.04874001":"0.00559094","0.04883238":"0.10000000","0.04887713":"0.09149646","0.04888000":"2.57003081","0.04889775":"0.02000000","0.04889949":"0.00226996","0.04890000":"5.26976751","0.04890925":"0.04309282","0.04892042":"0.21287721","0.04892681":"0.65231645","0.04900000":"43.99408869","0.04914000":"0.10000000","0.04925000":"0.00499500","0.04926499":"0.26834838","0.04926854":"0.00203000","0.04930000":"0.00811360","0.04934500":"1.00000000","0.04935001":"0.22019537","0.04940000":"0.64735021","0.04941394":"1.79327365","0.04945655":"6.99300001","0.04947572":"6.86786879","0.04948000":"0.20262400","0.04948816":"101.03424718","0.04950000":"2.20870871","0.04955271":"0.17062101","0.04958949":"8.77262189","0.04962261":"0.02416002","0.04965000":"1.99800000","0.04968001":"50.00000000","0.04975000":"0.80000000","0.04976148":"5.00000000","0.04980601":"0.03000000","0.04982360":"0.05000000","0.04985871":"0.58695558","0.04988040":"6.19864928","0.04988041":"0.00191741","0.04990000":"0.00592988","0.04990973":"1.00000000","0.04998559":"1.00000000","0.04999998":"0.50000000","0.04999999":"0.00220000","0.05000000":"623.94872426","0.05000010":"5.00000000","0.05002344":"33.55321794","0.05004102":"0.30088465","0.05010000":"5.00798404","0.05020000":"0.44000000","0.05023997":"35.49852904","0.05025000":"0.00499500","0.05040000":"0.06633000","0.05044915":"0.02551644","0.05050000":"2.00000000","0.05078769":"0.00416286","0.05080000":"0.07450000","0.05090000":"0.00785855","0.05093006":"1.70526598","0.05096000":"0.19625200","0.05098077":"0.00797889","0.05100000":"12.00895221","0.05102248":"0.00197952","0.05103000":"0.05908895","0.05110000":"0.29354207","0.05111880":"0.03500000","0.05113000":"0.19608700","0.05113298":"1.24051242","0.05120000":"0.04987500","0.05125000":"0.00499500","0.05127500":"0.01000000","0.05131086":"0.03436851","0.05139452":"3.00000000","0.05145000":"0.09424800","0.05147000":"0.42230000","0.05150000":"2.00000000","0.05152000":"10.00000000","0.05160369":"0.16186633","0.05166009":"0.03333000","0.05170000":"0.00773695","0.05175649":"0.40000000","0.05187600":"3.00000000","0.05189775":"0.01000000","0.05194280":"0.05000000","0.05200000":"65.21911303","0.05200890":"0.05000000","0.05205640":"0.03000000","0.05210000":"0.27260000","0.05220065":"1.00000000","0.05224090":"0.05000000","0.05225000":"0.00499500","0.05225446":"0.30000000","0.05227780":"0.05000000","0.05228503":"0.05565445","0.05232220":"0.05000000","0.05242449":"0.00914338","0.05243573":"0.00924425","0.05243710":"0.12000000","0.05244226":"0.01172868","0.05250000":"4.20761905","0.05250001":"0.20698366","0.05253500":"0.00211287","0.05257500":"0.10184500","0.05265838":"0.01944324","0.05270400":"2.80387332","0.05290000":"1.50000000","0.05299050":"4.00330139","0.05299999":"0.00190566","0.05300000":"7.82090767","0.05311350":"0.00357683","0.05314051":"0.77926871","0.05320000":"1.00610497","0.05325000":"0.00499500","0.05330000":"0.00750470","0.05340000":"0.07790319","0.05345000":"1.00000000","0.05350000":"2.00000000","0.05355000":"0.14988600","0.05367004":"0.30000000","0.05368001":"50.00000000","0.05371000":"5.22995159","0.05375000":"1.01996623","0.05376000":"0.18601190","0.05385871":"1.00000000","0.05389775":"0.01000000","0.05390000":"22.00000000","0.05394540":"1.27837024","0.05396000":"0.12354831","0.05400000":"18.09283506","0.05410000":"0.00739372","0.05417867":"0.36143386","0.05422000":"5.00000000","0.05425000":"0.00499500","0.05431536":"0.10000000","0.05432000":"30.00000000","0.05433907":"1.35093135","0.05436935":"0.21695347","0.05440894":"0.03468148","0.05442800":"0.10000000","0.05448849":"91.76248200","0.05450000":"2.00000000","0.05460000":"0.20512900","0.05475001":"0.08092734","0.05480000":"0.06900000","0.05483967":"2.07292501","0.05487900":"5.14939613","0.05488001":"0.00189175","0.05489000":"0.00550000","0.05490000":"0.00728598","0.05490973":"1.00000000","0.05491000":"0.20000000","0.05493311":"0.56761375","0.05498300":"0.38776097","0.05499999":"0.00200000","0.05500000":"53.67772757","0.05501111":"0.18550774","0.05501621":"8.00000000","0.05502121":"0.10000000","0.05514000":"0.18135655","0.05525000":"0.00499500","0.05546800":"0.00200115","0.05550000":"2.00000000","0.05550058":"0.02126410","0.05560000":"0.10815774","0.05565000":"0.19146227","0.05568827":"0.02032539","0.05570000":"0.00718133","0.05580050":"0.08000000","0.05583001":"0.00187410","0.05589775":"0.01000000","0.05590000":"0.00179998","0.05598000":"1.00000000","0.05600000":"11.65382245","0.05610000":"0.06740000","0.05613436":"0.01799519","0.05620000":"0.26690391","0.05620610":"0.03333002","0.05621000":"0.60000000","0.05621800":"0.04990000","0.05625000":"0.00499500","0.05625871":"0.97407195","0.05627000":"1.99800000","0.05633317":"45.15937053","0.05640601":"1.37380045","0.05650000":"2.00707965","0.05660600":"0.17965687","0.05665851":"1.50000000","0.05666000":"1.00000000","0.05668001":"20.00000000","0.05670000":"9.17800754","0.05680680":"0.03000000","0.05696549":"0.00196996","0.05700000":"5.15086383","0.05700006":"0.10000000","0.05707070":"52.38800632","0.05712356":"0.33428820","0.05712459":"0.68900000","0.05720000":"0.00355768","0.05721001":"0.10000000","0.05725000":"0.00499500","0.05726499":"0.25711050","0.05726664":"0.54782086","0.05730000":"0.00698081","0.05739099":"0.33729192","0.05740000":"0.06580000","0.05746625":"0.12149266","0.05750000":"3.30000000","0.05754505":"1.00000000","0.05763796":"0.36125844","0.05770600":"0.00182762","0.05772900":"0.38969621","0.05774670":"0.05000000","0.05775000":"0.18449999","0.05776148":"5.00000000","0.05777000":"0.07752425","0.05777306":"0.21858755","0.05781024":"0.05237000","0.05789000":"0.00172801","0.05789775":"0.01000000","0.05790000":"0.50000000","0.05797000":"0.00173000","0.05800000":"74.78375794","0.05800010":"0.07558331","0.05800255":"0.35313881","0.05810000":"0.00688469","0.05824870":"0.05006427","0.05824995":"4.42343654","0.05825000":"0.00499500","0.05830000":"0.01034762","0.05836256":"0.24000000","0.05841502":"3.92162399","0.05842070":"0.00365429","0.05850000":"2.07985000","0.05853425":"0.05500000","0.05860000":"0.07050776","0.05865000":"0.06304640","0.05866210":"0.83641742","0.05870000":"0.06430000","0.05877981":"0.25804059","0.05880000":"0.70000000","0.05880001":"0.18120535","0.05883026":"0.01536200","0.05883239":"0.00188671","0.05883325":"0.09680440","0.05883711":"2.00000000","0.05887770":"0.00298030","0.05889000":"0.13994000","0.05889775":"0.01000000","0.05890000":"0.23006425","0.05890560":"0.00175444","0.05900000":"4.11891611","0.05900722":"2.50000000","0.05907900":"0.49950000","0.05910485":"0.82209997","0.05917316":"0.25496430","0.05918500":"0.51003060","0.05921001":"0.10000000","0.05921160":"0.05000000","0.05922080":"0.12000000","0.05925000":"0.00499500","0.05932401":"0.04503634","0.05934500":"1.00000000","0.05936751":"0.93112807","0.05940601":"1.00000000","0.05942000":"0.05241696","0.05948844":"84.04992902","0.05950000":"2.00000000","0.05957999":"0.03320011","0.05958007":"16.28454810","0.05960000":"0.01724116","0.05960200":"0.33555920","0.05970000":"0.00670017","0.05976000":"1.17198906","0.05984428":"0.10000000","0.05985001":"0.17802631","0.05985997":"0.35880093","0.05988000":"1.28034501","0.05990000":"0.10000000","0.05990973":"1.00000000","0.05991000":"4.00775618","0.05993341":"0.04144024","0.05993727":"0.00172173","0.05995228":"0.05500000","0.05997604":"0.32787423","0.05999000":"22.72140037","0.05999999":"0.00183333","0.06000000":"54.19085476","0.06000006":"0.10000000","0.06000990":"0.10000000","0.06010000":"2.15940000","0.06020000":"0.51866984","0.06021000":"0.39700000","0.06025000":"0.00499500","0.06030842":"0.02981504","0.06040601":"1.00000000","0.06042880":"0.05045561","0.06043977":"2.66974799","0.06050000":"3.00661158","0.06061059":"2.69698865","0.06090000":"0.27495690","0.06100000":"5.33952572","0.06100461":"0.17882284","0.06100990":"0.10000000","0.06101041":"0.51971238","0.06106080":"0.49388003","0.06108010":"0.00181728","0.06113000":"0.11086113","0.06121001":"0.10000000","0.06122608":"0.03500000","0.06123000":"1.00000000","0.06125000":"0.00499500","0.06130000":"0.00652529","0.06131000":"0.20000000","0.06132000":"0.10871929","0.06133304":"2.00000000","0.06139452":"3.33031825","0.06140000":"0.06160000","0.06150000":"3.00000000","0.06152000":"10.00000000","0.06156290":"0.02500000","0.06160980":"0.03000000","0.06163213":"0.03398545","0.06165843":"0.00538132","0.06181440":"0.05000000","0.06182999":"0.00868356","0.06188000":"0.56000000","0.06189775":"0.01000000","0.06190000":"0.76155088","0.06193525":"0.64204466","0.06195000":"0.17199152","0.06199900":"0.49950000","0.06200000":"19.23409985","0.06200599":"0.10000000","0.06205000":"0.12977976","0.06208000":"0.10738832","0.06210000":"0.00644123","0.06215366":"0.24420526","0.06220065":"1.00000000","0.06225000":"0.00499500","0.06225380":"0.05010956","0.06230261":"0.34742239","0.06234174":"0.57718976","0.06247019":"0.01685263","0.06249001":"0.16036663","0.06250000":"3.05000000","0.06260000":"0.11830452","0.06260420":"0.04044921","0.06270000":"0.06020000","0.06287400":"5.00000000","0.06289044":"0.22300000","0.06290000":"0.10635931","0.06296288":"0.02057107","0.06296500":"5.57621143","0.06300000":"3.43424845","0.06300500":"0.10000000","0.06302563":"0.00178054","0.06310000":"0.00303664","0.06315700":"0.00996539","0.06319454":"0.42907969","0.06320408":"0.20000006","0.06322916":"0.00159736","0.06325000":"0.00499500","0.06340500":"0.10011370","0.06342042":"0.15933976","0.06343999":"0.45849013","0.06347000":"0.08008164","0.06350000":"3.00000000","0.06353000":"0.00174000","0.06354001":"0.10679310","0.06354002":"2.32242013","0.06355000":"0.00161144","0.06363000":"0.35060012","0.06367004":"0.30423434","0.06370000":"2.00627944","0.06373497":"0.22412296","0.06376003":"2.88591936","0.06382851":"0.01001000","0.06389775":"0.01000000","0.06390000":"0.10000000","0.06393000":"0.15642109","0.06394869":"0.00266365","0.06395000":"2.00309133","0.06397000":"0.00157000","0.06400000":"31.21401894","0.06409500":"0.10000000","0.06410000":"0.05900000","0.06412578":"0.64900002","0.06415000":"0.00173031","0.06420000":"0.20000000","0.06424440":"0.01650000","0.06425000":"0.00499500","0.06431536":"0.10000000","0.06439500":"0.50000000","0.06440493":"5.32420989","0.06443993":"0.44890732","0.06444320":"0.05000000","0.06450000":"3.00620156","0.06457500":"0.00158587","0.06459001":"0.11815540","0.06460000":"0.04300966","0.06480000":"40.00000000","0.06488594":"77.05828458","0.06490000":"0.50000000","0.06490973":"1.00000000","0.06491582":"0.00159286","0.06499999":"0.00169231","0.06500000":"18.30260934","0.06500722":"5.00000000","0.06510001":"0.16366935","0.06517281":"0.00172188","0.06524150":"0.08000000","0.06525000":"0.00499500","0.06526020":"0.15300000","0.06529180":"0.05400000","0.06530000":"0.00612558","0.06532500":"0.25220000","0.06534000":"0.15304561","0.06536000":"0.80000000","0.06537380":"0.65813743","0.06540000":"0.05780000","0.06540536":"0.16328183","0.06550000":"3.08101829","0.06560000":"0.00156109","0.06584696":"0.10068998","0.06589775":"0.01000000","0.06590000":"0.10000000","0.06598461":"0.01700000","0.06598833":"0.05500000","0.06600000":"10.05053030","0.06610000":"0.00605144","0.06625000":"0.00499500","0.06630000":"0.20000000","0.06640425":"0.23073083","0.06644000":"0.00170000","0.06645502":"0.00167030","0.06650000":"3.00000000","0.06654696":"0.10000000","0.06655202":"0.00315542","0.06656455":"2.00000000","0.06662500":"0.00153707","0.06665600":"0.13951544","0.06667756":"0.05000000","0.06668001":"20.00000000","0.06670000":"0.05660000","0.06690000":"0.00597908","0.06697000":"0.00150000","0.06698000":"0.00325252","0.06700000":"5.93156280","0.06700001":"0.10076795","0.06700006":"0.10000000","0.06700743":"0.13794885","0.06703569":"0.37146068","0.06705999":"0.19950000","0.06708987":"0.90000000","0.06714082":"0.06153801","0.06720001":"0.15855469","0.06725000":"0.00499500","0.06733436":"0.04228580","0.06750000":"3.00000000","0.06760000":"0.30000000","0.06765000":"0.00151378","0.06770000":"0.00590842","0.06779999":"0.03199801","0.06786872":"0.02012214","0.06788000":"0.99900000","0.06789775":"0.01000000","0.06790000":"0.20000000","0.06794000":"0.14718900","0.06796148":"5.00000000","0.06798426":"0.10000000","0.06800000":"9.88486766","0.06801500":"0.10055622","0.06810000":"0.20234287","0.06811890":"0.01800000","0.06812001":"0.52721658","0.06815944":"1.16605483","0.06821000":"7.17103625","0.06821060":"0.08100000","0.06825000":"0.00499500","0.06825480":"0.05400000","0.06827490":"0.09000000","0.06832013":"0.00164256","0.06835619":"0.00934300","0.06840000":"0.00146361","0.06842000":"0.29970001","0.06850000":"3.50583942","0.06850248":"0.60008935","0.06866108":"0.20395209","0.06867500":"0.00149119","0.06877501":"0.00161395","0.06880000":"50.24000000","0.06889000":"0.10000000","0.06889775":"0.01000000","0.06890000":"20.11055041","0.06898000":"0.00150415","0.06900000":"19.30139885","0.06905500":"0.10000000","0.06909250":"0.49960000","0.06914000":"0.15261512","0.06920070":"0.05000000","0.06925000":"0.00499500","0.06930000":"0.15952201","0.06940000":"0.05450000","0.06941400":"0.19560000","0.06943000":"0.07482924","0.06948859":"71.95424862","0.06950000":"3.35164684","0.06958000":"1.99757499","0.06960690":"0.01684427","0.06964700":"0.00148363","0.06966514":"0.05930817","0.06969000":"0.00148216","0.06970000":"2.65945387","0.06972401":"0.05000000","0.06980000":"1.91367419","0.06980126":"0.44078871","0.06987173":"0.20671023","0.06990000":"0.35250000","0.06990973":"1.00000000","0.06991876":"1.00000000","0.06992001":"0.10064610","0.06995654":"0.03722699","0.06997000":"0.00143000","0.06999999":"0.00157143","0.07000000":"49.97635910","0.07000006":"0.10000000","0.07000070":"1.00000000","0.07005999":"0.30000000","0.07010000":"5.00570614","0.07011855":"0.30000000","0.07013725":"0.00152656","0.07021257":"0.00159828","0.07024855":"0.94940000","0.07025000":"0.00499500","0.07025860":"0.00157317","0.07046000":"0.07375417","0.07049317":"0.01250112","0.07050000":"4.50600000","0.07056500":"0.00285661","0.07070000":"1.11253379","0.07072500":"0.00147779","0.07072760":"1.17672980","0.07078750":"0.00141562","0.07083999":"0.21650888","0.07090000":"0.00564175","0.07100000":"14.73942000","0.07100111":"0.10015757","0.07110250":"0.27944000","0.07112887":"0.00141050","0.07116780":"0.12000000","0.07124380":"0.02575386","0.07125000":"0.00499500","0.07131691":"0.00164358","0.07140001":"0.14922794","0.07144996":"0.03992000","0.07150000":"4.00000000","0.07152000":"10.00000000","0.07152887":"0.00140400","0.07153000":"0.05442360","0.07159412":"5.00000000","0.07159990":"0.05840542","0.07160470":"0.04033339","0.07161470":"0.00139700","0.07163617":"14.00000000","0.07164071":"3.63445895","0.07168000":"0.18601190","0.07170000":"0.00557881","0.07173021":"0.12666575","0.07175000":"0.00151733","0.07187459":"0.05748502","0.07188270":"0.28000000","0.07189540":"10.00000000","0.07189775":"0.01000000","0.07190000":"0.10000000","0.07190511":"0.10000000","0.07195513":"0.29905050","0.07198000":"1.57296624","0.07200000":"59.88840653","0.07201900":"0.10000000","0.07202601":"0.03030602","0.07206110":"0.05052386","0.07210000":"0.24618238","0.07216000":"0.00155514","0.07220065":"1.00000000","0.07222887":"0.00139000","0.07224324":"0.15226333","0.07225000":"0.00499500","0.07227600":"1.06729800","0.07232595":"0.01536996","0.07235273":"0.00629172","0.07249000":"0.00141207","0.07250000":"832.99431180","0.07252555":"0.30000000","0.07254000":"0.00289567","0.07259002":"0.00152913","0.07260000":"0.03642496","0.07261470":"0.00137800","0.07262003":"0.02000000","0.07264700":"0.00142064","0.07265700":"0.00138375","0.07270000":"0.20000000","0.07277500":"0.00143617","0.07278000":"0.08933230","0.07280719":"0.00151647","0.07284101":"0.14025049","0.07288500":"0.30000000","0.07290500":"0.10055764","0.07295130":"1.06039050","0.07299999":"0.00138000","0.07300000":"98.58329535","0.07301000":"0.07060378","0.07306208":"0.05655070","0.07311450":"0.00138148","0.07316375":"0.39475665","0.07320000":"2.99700000","0.07324000":"0.42490749","0.07325000":"0.00499500","0.07330000":"0.46223472","0.07331212":"0.01033522","0.07340000":"0.05150000","0.07342781":"0.00680940","0.07345000":"1.00000000","0.07348971":"0.40000000","0.07350000":"13.78282333","0.07350001":"0.14496428","0.07352000":"0.22723492","0.07354000":"0.15000000","0.07355599":"0.10026934","0.07356000":"2.56282554","0.07360226":"1.38600000","0.07361470":"0.00135900","0.07366000":"0.02500000","0.07367004":"0.10000000","0.07370000":"0.61000000","0.07380000":"0.06138763","0.07389775":"0.01000000","0.07390240":"0.30000000","0.07393855":"0.54306550","0.07399990":"0.99900001","0.07400000":"10.74083951","0.07400499":"0.10000000","0.07405265":"0.01085199","0.07409400":"0.29320565","0.07410000":"0.00539812","0.07413168":"0.00161874","0.07414500":"0.00135000","0.07422564":"0.00843152","0.07425000":"0.00499500","0.07427064":"0.99061302","0.07431536":"0.10000000","0.07432001":"6.91924985","0.07433001":"1.01898000","0.07443524":"0.10020679","0.07443993":"0.33000000","0.07450000":"4.00000000","0.07454000":"0.04461416","0.07455700":"0.00134800","0.07460000":"0.01000000","0.07461470":"0.00134100","0.07470000":"0.05060000","0.07472000":"6.11913003","0.07475010":"0.02005722","0.07479317":"0.01139459","0.07480000":"0.01363636","0.07488694":"66.76730726","0.07490000":"0.25534046","0.07493000":"0.00155806","0.07498977":"0.10464268","0.07499999":"0.00146667","0.07500000":"36.56973740","0.07521363":"5.10873355","0.07525000":"0.00499500","0.07540000":"3.88612894","0.07545700":"0.00133479","0.07549990":"0.00139789","0.07550000":"4.29153739","0.07553370":"0.01196432","0.07553500":"0.20010380","0.07555133":"0.07576459","0.07555421":"0.01861188","0.07556000":"0.06876687","0.07560000":"0.14093750","0.07561470":"0.00132300","0.07567425":"0.32507561","0.07570000":"0.00528402","0.07572500":"0.07377868","0.07577180":"0.05452836","0.07588500":"0.02097139","0.07589775":"0.01000000","0.07592772":"0.10000000","0.07600000":"11.09499999","0.07601000":"0.00300706","0.07601248":"0.48835117","0.07602599":"0.00146002","0.07610000":"0.04970000","0.07612848":"0.66000000","0.07620000":"0.04323377","0.07622257":"0.01500000","0.07625000":"0.04499500","0.07627423":"0.01256253","0.07630000":"0.15000000","0.07632001":"0.53048691","0.07640000":"0.03655810","0.07650000":"4.10529631","0.07651598":"0.14338129","0.07656455":"1.00000000","0.07658000":"0.06800232","0.07658470":"1.00000000","0.07661470":"0.00130600","0.07668001":"20.00000000","0.07670000":"0.05276861","0.07675000":"0.05000000","0.07678086":"0.03335942","0.07680660":"0.05000000","0.07690000":"0.64900000","0.07698077":"0.10000000","0.07700000":"6.04818991","0.07700211":"2.99320660","0.07701475":"0.01319066","0.07709000":"0.05011260","0.07724961":"0.20028389","0.07725000":"0.00499500","0.07729000":"0.25762582","0.07730000":"0.00517465","0.07736815":"0.61594493","0.07737996":"5.45033036","0.07740000":"0.08907441","0.07745000":"0.05000000","0.07750000":"4.10000000","0.07751793":"0.09980000","0.07758050":"0.03932103","0.07760000":"0.11695562","0.07761470":"0.00128900","0.07763003":"0.15811249","0.07767800":"0.70805118","0.07770000":"5.41527328","0.07770001":"0.13712837","0.07775528":"0.01385019","0.07777777":"5.40599317","0.07780000":"0.05000000","0.07781691":"0.02581077","0.07788752":"1.30269600","0.07789332":"0.05304322","0.07789775":"0.01000000","0.07789894":"0.14977500","0.07790000":"4.13962500","0.07790240":"0.30000000","0.07792001":"0.05006311","0.07793988":"0.00143982","0.07794180":"0.01500000","0.07794227":"0.07079307","0.07797000":"0.00135170","0.07799991":"3.53055283","0.07800000":"15.44243339","0.07810000":"0.00512164","0.07811000":"0.06528559","0.07811050":"1.17651410","0.07812700":"0.30000000","0.07814031":"1.16404526","0.07815343":"0.03063625","0.07818236":"0.00129185","0.07819051":"0.00703410","0.07824132":"0.29585510","0.07825000":"0.00499500","0.07833468":"0.51599889","0.07835000":"0.05000000","0.07836000":"0.25000000","0.07838323":"0.00130542","0.07843631":"0.00229485","0.07844022":"0.06918497","0.07847000":"0.00278655","0.07849581":"0.01454270","0.07850000":"5.10844403","0.07854591":"1.00000000","0.07857424":"2.79977717","0.07861470":"0.00127300","0.07861560":"0.08000000","0.07862000":"0.06486170","0.07862131":"0.01017494","0.07866000":"0.00998000","0.07870000":"0.31440001","0.07877000":"0.05000000","0.07879063":"0.23000000","0.07882110":"0.10000000","0.07882999":"0.00887986","0.07887001":"0.49101180","0.07889000":"0.36744524","0.07889775":"0.01000000","0.07890000":"0.53721715","0.07891012":"0.20000000","0.07898972":"0.07702868","0.07899912":"0.00687175","0.07899998":"29.91879243","0.07900000":"36.29244143","0.07902400":"0.09860000","0.07904591":"1.60930279","0.07907671":"0.00649664","0.07909001":"1.02433522","0.07913000":"0.06444330","0.07920000":"0.69366361","0.07923633":"0.01526984","0.07925000":"0.00499500","0.07935100":"0.06970000","0.07935418":"0.32369337","0.07937000":"0.05000000","0.07938247":"8.69186706","0.07940622":"2.03196600","0.07943000":"0.00380799","0.07948520":"28.09321172","0.07948869":"62.90202256","0.07949000":"0.00140000","0.07949002":"0.00180834","0.07950000":"4.10000000","0.07950252":"1.39594133","0.07955050":"5.00000000","0.07958381":"0.04446130","0.07958999":"0.69839041","0.07960447":"0.47952200","0.07961470":"0.00125700","0.07964000":"0.06403025","0.07970000":"0.77501883","0.07971026":"0.14644839","0.07980000":"0.16486842","0.07986000":"0.05000000","0.07988375":"0.30070397","0.07989200":"0.05873320","0.07990000":"0.47526317","0.07991207":"0.14775225","0.07994999":"0.10000000","0.07997686":"0.01603333","0.07999999":"0.00137500","0.08000000":"89.93769915","0.08000006":"0.10000000","0.08002710":"0.12645553","0.08003036":"1.28847541","0.08009724":"0.75929228","0.08010000":"1.04720000","0.08016000":"0.08953578","0.08021026":"0.06659497","0.08025000":"0.00499500","0.08026380":"6.30000000","0.08031026":"0.07999999","0.08031308":"0.05144507","0.08043977":"2.50000000","0.08044081":"0.00621575","0.08047000":"0.06000000","0.08048000":"0.00139437","0.08049502":"1.26500000","0.08050000":"4.10496895","0.08050252":"1.30000000","0.08054791":"1.72639569","0.08059200":"0.02000000","0.08061470":"0.00124100","0.08064827":"0.12548055","0.08065000":"0.30000000","0.08067000":"0.12643969","0.08071738":"0.01683500","0.08079834":"0.01855315","0.08080000":"1.42576899","0.08085511":"0.01871333","0.08089000":"0.00137223","0.08089999":"0.05000000","0.08094000":"0.12354831","0.08099812":"1.92968584","0.08100000":"20.87398935","0.08100004":"59.88464862","0.08107954":"0.04426645","0.08108000":"0.00604714","0.08109359":"0.25015602","0.08111000":"2.04000000","0.08111823":"0.10000000","0.08111835":"0.05988000","0.08117000":"0.01445995","0.08117939":"0.00383211","0.08117959":"0.12507786","0.08120000":"2.43268053","0.08125000":"0.00499500","0.08126475":"0.01290113","0.08126987":"0.12631440","0.08127020":"0.06313131","0.08129327":"1.20000000","0.08130000":"1.13236602","0.08138855":"0.01211559","0.08139500":"0.31189828","0.08139613":"0.00131005","0.08140000":"1.04640000","0.08145000":"0.02345319","0.08145791":"0.01767675","0.08146300":"0.02532909","0.08150000":"6.00000000","0.08151990":"0.37279239","0.08152000":"10.00000000","0.08152520":"2.00000000","0.08153688":"0.10000000","0.08160000":"1.00000000","0.08161470":"0.00122600","0.08169000":"0.00910138","0.08170000":"1.00000000","0.08173000":"0.04997871","0.08176001":"0.01817555","0.08176450":"0.02000000","0.08180000":"1.01873913","0.08182418":"16.60377538","0.08189775":"0.01000000","0.08190000":"1.13009615","0.08200000":"23.60778894","0.08210000":"1.00487211","0.08217945":"11.71786274","0.08219844":"0.01856058","0.08220000":"1.00000000","0.08220065":"1.00000000","0.08220366":"0.02705370","0.08221500":"1.00000000","0.08222760":"0.02438014","0.08225000":"0.00499500","0.08228200":"20.00000000","0.08230000":"1.00000000","0.08238000":"0.02544135","0.08240000":"1.00000000","0.08248000":"0.00372484","0.08250000":"13.00411317","0.08251396":"2.00000000","0.08252331":"0.01992091","0.08255252":"1.00000000","0.08260000":"0.25246800","0.08261470":"0.00121100","0.08263000":"1.24253732","0.08270000":"1.11606946","0.08275000":"0.04542109","0.08289999":"0.05000000","0.08290000":"0.00482510","0.08293270":"1.08498502","0.08293896":"0.01948861","0.08299000":"0.00248908","0.08300000":"10.86351147","0.08301501":"0.02730828","0.08307521":"0.01789848","0.08310643":"0.00398092","0.08313195":"0.05292718","0.08320000":"0.00261484","0.08323800":"0.03995483","0.08325000":"0.00499500","0.08328203":"0.09079421","0.08330500":"17.21774401","0.08330850":"0.05022784","0.08333217":"3.13076629","0.08333374":"0.05452176","0.08335260":"0.28920000","0.08339251":"0.24515335","0.08344500":"0.02245408","0.08348849":"0.02801770","0.08349189":"0.00119892","0.08350000":"6.00000000","0.08353206":"1.20784373","0.08353401":"0.00263102","0.08357251":"0.24132117","0.08361470":"0.00119700","0.08363500":"0.06323862","0.08364893":"0.07231129","0.08364916":"0.07231109","0.08365000":"6.38228846","0.08367949":"0.02046304","0.08368000":"0.03272097","0.08369880":"0.03617500","0.08370000":"0.00477898","0.08371310":"0.30626650","0.08377000":"0.02435081","0.08377351":"0.12109971","0.08380501":"0.40554961","0.08383711":"0.24219942","0.08384422":"0.00128100","0.08385441":"0.24219942","0.08389775":"0.01000000","0.08390000":"7.38779674","0.08392518":"0.00300977","0.08393000":"0.50000000","0.08393270":"1.30000000","0.08400000":"65.64125268","0.08401798":"0.08372428","0.08403549":"0.04454919","0.08405500":"0.10000000","0.08410000":"0.15742988","0.08414973":"0.03627235","0.08416530":"0.00877109","0.08417524":"0.24130830","0.08419016":"0.10000000","0.08420000":"0.02997000","0.08423005":"0.01343940","0.08423525":"1.43000000","0.08423684":"0.02122875","0.08425000":"0.00499500","0.08428188":"0.02751943","0.08430000":"0.00120334","0.08431000":"0.10000000","0.08431536":"0.10000000","0.08432000":"0.40000000","0.08433290":"0.01606947","0.08434000":"0.06986000","0.08435046":"5.00000000","0.08437294":"0.00777465","0.08439801":"0.19494269","0.08441500":"0.00147395","0.08442002":"0.02148620","0.08443993":"0.33000000","0.08444476":"10.54366917","0.08445300":"4.97404685","0.08449484":"0.40271143","0.08450000":"6.56343094","0.08451150":"0.21660082","0.08458105":"0.35000000","0.08461470":"0.00118200","0.08469000":"0.10000000","0.08470000":"0.87000000","0.08472200":"0.09920400","0.08479000":"0.02406939","0.08485000":"0.06000000","0.08487000":"0.10000000","0.08488200":"58.90530384","0.08490000":"25.26720401","0.08491222":"0.06573392","0.08493120":"0.20664924","0.08495505":"0.25000000","0.08499900":"0.59950000","0.08499999":"0.00129412","0.08500000":"52.75382253","0.08502407":"0.40562267","0.08504000":"0.10950000","0.08507000":"0.12333334","0.08508900":"0.01537269","0.08510000":"0.27081885","0.08511800":"1.19597044","0.08517000":"0.02114367","0.08517343":"0.10000000","0.08520000":"0.17107699","0.08522504":"0.20000000","0.08524000":"0.15642109","0.08525000":"0.00499500","0.08527661":"1.27000000","0.08540000":"0.04430000","0.08540500":"0.07755290","0.08541032":"0.07659501","0.08542747":"0.09790063","0.08544220":"0.00128100","0.08544300":"0.07785728","0.08547600":"1.13985900","0.08550000":"5.01521630","0.08552075":"0.02735204","0.08555000":"0.50000000","0.08560000":"1.00000000","0.08561470":"0.00117000","0.08561584":"0.10437871","0.08562000":"0.01447812","0.08562955":"0.12733137","0.08567196":"0.07873291","0.08570000":"0.09018376","0.08576528":"0.00525976","0.08581500":"0.02854882","0.08587000":"0.00120000","0.08589775":"0.01000000","0.08590000":"1.89315057","0.08596684":"0.00222195","0.08597061":"0.07981308","0.08599000":"2.00000000","0.08599990":"0.31788180","0.08600000":"20.50689318","0.08602309":"0.00255490","0.08607572":"0.01447812","0.08610001":"0.12375000","0.08619502":"0.11184838","0.08638168":"12.08535949","0.08640000":"4.18399210","0.08640500":"0.07059042","0.08642123":"0.00512069","0.08644000":"0.30000000","0.08649993":"0.00128655","0.08650000":"5.32544984","0.08651701":"0.99850000","0.08655556":"0.10000000","0.08659011":"0.19522766","0.08659142":"0.10000000","0.08660000":"16.08081758","0.08660516":"0.04770746","0.08661470":"0.00500000","0.08662000":"0.00577233","0.08662500":"0.02420563","0.08664000":"0.61920761","0.08665500":"0.00139077","0.08666000":"0.36113335","0.08666682":"0.05089499","0.08670000":"0.04360000","0.08674000":"0.05000000","0.08676000":"0.42085520","0.08682000":"0.11862394","0.08684000":"0.12104404","0.08684910":"0.11543000","0.08685589":"0.01464713","0.08685608":"0.48779514","0.08686470":"0.00500000","0.08695001":"2.75206611","0.08697098":"0.25097982","0.08699001":"0.20000000","0.08699993":"0.00128655","0.08700000":"47.66235207","0.08702500":"0.05000000","0.08707650":"0.00291805","0.08711470":"0.00550000","0.08712000":"0.15304561","0.08712100":"0.03989986","0.08713000":"0.03778409","0.08713800":"0.03464060","0.08716712":"0.02406690","0.08717343":"0.10000000","0.08720000":"0.10000000","0.08721221":"0.15721942","0.08721420":"0.01335284","0.08730500":"0.60000000","0.08736470":"0.00300000","0.08737000":"0.00115256","0.08737996":"5.47000000","0.08738416":"1.00000000","0.08738820":"5.00000000","0.08740000":"0.04904457","0.08740500":"0.07612477","0.08743597":"0.00571847","0.08745609":"0.00973048","0.08749993":"0.00125714","0.08750000":"4.80832372","0.08753000":"0.11711618","0.08755556":"0.10000000","0.08761000":"4.46712828","0.08761005":"1.05803905","0.08761470":"0.00550000","0.08770000":"0.67572909","0.08770660":"0.05013584","0.08776000":"0.30000000","0.08777000":"0.00115256","0.08777706":"0.01464713","0.08778999":"15.65015284","0.08783000":"0.00156652","0.08784010":"0.20000000","0.08786470":"0.00500000","0.08787045":"0.43624135","0.08789000":"3.00000000","0.08789008":"0.52194080","0.08789775":"0.01000000","0.08790000":"0.13180200","0.08793981":"0.02385512","0.08797500":"0.05987999","0.08799000":"0.12000000","0.08799236":"2.61272155","0.08799993":"0.00125714","0.08800000":"14.67195763","0.08801000":"0.15000000","0.08802103":"0.11186303","0.08803250":"0.05994000","0.08810000":"0.87048303","0.08811470":"0.00550000","0.08811600":"0.02380816","0.08820001":"0.12080356","0.08829062":"0.00942849","0.08829100":"0.01450071","0.08829815":"0.02995374","0.08830000":"0.85203145","0.08830236":"0.02994000","0.08836470":"0.00300000","0.08843200":"0.10000000","0.08849000":"0.02768144","0.08849993":"0.00125714","0.08850000":"7.82579872","0.08852000":"0.00564844","0.08852661":"0.05987999","0.08853131":"0.00125379","0.08854440":"1.51780855","0.08855556":"0.10000000","0.08858497":"0.02316123","0.08858990":"0.19970002","0.08859520":"0.21000000","0.08861005":"0.05888200","0.08861700":"0.69816268","0.08865904":"0.01120926","0.08867001":"0.15155019","0.08869822":"0.01464713","0.08874000":"0.05000000","0.08876000":"0.30000000","0.08876850":"0.05037561","0.08878000":"3.99600000","0.08878700":"0.00228675","0.08880000":"0.02016785","0.08881374":"1.04779784","0.08882070":"1.00000000","0.08882110":"0.09000000","0.08883000":"0.02000000","0.08885022":"1.61995265","0.08886470":"0.00500000","0.08889000":"9.91354541","0.08889775":"0.01000000","0.08890000":"0.00383656","0.08892408":"0.55847666","0.08896750":"0.02358039","0.08897532":"0.01422661","0.08899000":"0.03527310","0.08899993":"0.00123595","0.08900000":"8.90419928","0.08900961":"0.02993999","0.08902000":"0.06889410","0.08902340":"5.03093809","0.08902500":"0.05000000","0.08906395":"0.02579832","0.08907600":"0.11254400","0.08908800":"0.30000000","0.08910000":"0.00233715","0.08914000":"0.20747631","0.08916668":"0.01170937","0.08917343":"0.10000000","0.08923008":"0.04018486","0.08924191":"0.05987999","0.08926820":"0.99308583","0.08927498":"0.00131960","0.08930666":"0.00225962","0.08932039":"0.04625721","0.08932740":"0.00504756","0.08933021":"0.20306510","0.08935705":"0.00124209","0.08935889":"0.01500000","0.08936470":"0.00500000","0.08940000":"0.04230000","0.08942000":"0.34608083","0.08943500":"0.00802086","0.08944561":"0.00135298","0.08949993":"0.00123595","0.08950000":"36.96865892","0.08950164":"0.02122875","0.08951492":"0.41098961","0.08952000":"10.58583440","0.08953581":"0.02388901","0.08955556":"0.10000000","0.08956963":"0.02349820","0.08957699":"0.00954804","0.08960767":"0.20000000","0.08961470":"0.00550000","0.08964000":"0.25549074","0.08968388":"0.01115027","0.08969193":"0.00391969","0.08970000":"0.00237915","0.08974744":"0.08000000","0.08977000":"0.10000000","0.08977488":"55.69486078","0.08978500":"0.25000000","0.08982217":"0.04599880","0.08983003":"23.55719676","0.08985000":"0.06172037","0.08986470":"0.00500000","0.08986600":"1.26625124","0.08987000":"5.00000000","0.08988123":"0.40929423","0.08988900":"0.00200000","0.08990000":"0.59925000","0.08995000":"0.01222556","0.08995400":"0.01252745","0.08995808":"0.59757002","0.08996489":"1.00000000","0.08996830":"3.50995182","0.08998507":"0.00920714","0.08999900":"0.05493999","0.08999993":"0.00123595","0.08999999":"0.00122222","0.09000000":"382.27545243","0.09000001":"0.10000000","0.09000400":"0.02000000","0.09000447":"0.10000000","0.09002171":"0.06982500","0.09003700":"0.05000000","0.09003925":"0.05987999","0.09006307":"0.16915274","0.09007000":"0.00169825","0.09007400":"0.05000000","0.09008486":"0.02993999","0.09011100":"2.81267620","0.09011470":"0.00550000","0.09011500":"5.00000000","0.09012895":"0.02994000","0.09013000":"0.04530085","0.09014239":"0.01748428","0.09015706":"0.00661426","0.09019876":"0.70319186","0.09021750":"0.02993999","0.09030000":"0.14085679","0.09030554":"0.00160473","0.09031574":"0.57127847","0.09033325":"0.50000000","0.09036470":"0.00400000","0.09040000":"3.98785655","0.09041007":"0.00122773","0.09049993":"0.00123595","0.09050000":"2.74627034","0.09056825":"0.08981998","0.09057365":"1.56560207","0.09061470":"0.00550000","0.09061723":"0.01499382","0.09061811":"0.00954804","0.09062811":"0.01733546","0.09070000":"0.04170000","0.09071261":"0.00200000","0.09072451":"0.61607264","0.09073000":"0.00551085","0.09078000":"0.11042800","0.09085586":"0.03091344","0.09086470":"0.00500000","0.09088000":"0.30000000","0.09088796":"0.00354325","0.09090000":"0.27502750","0.09090889":"5.26925805","0.09090900":"0.53352200","0.09099208":"0.63939993","0.09099900":"1.18441536","0.09099939":"0.00110990","0.09099993":"0.00120879","0.09100000":"5.55443088","0.09100447":"0.10000000","0.09100501":"0.00200000","0.09100503":"49.80772000","0.09102409":"0.04539142","0.09106230":"0.11410432","0.09109486":"0.04030000","0.09109500":"0.00300000","0.09109605":"5.09189238","0.09111000":"0.50000000","0.09111470":"0.00550000","0.09111550":"0.77118728","0.09130000":"1.02000000","0.09138000":"0.04377325","0.09139687":"0.42224565","0.09144009":"3.85350453","0.09148000":"0.38941500","0.09149993":"0.00120879","0.09150000":"0.38735064","0.09150255":"0.00880431","0.09152000":"10.00000000","0.09159530":"0.00338445","0.09161470":"0.00500000","0.09161665":"0.18392617","0.09162000":"0.08187152","0.09165922":"0.00954804","0.09180000":"2.00099700","0.09188198":"0.03896831","0.09189437":"0.01859764","0.09189775":"0.01000000","0.09198000":"0.10871929","0.09199900":"0.36868326","0.09199993":"0.00119565","0.09200000":"6.61045754","0.09202608":"0.68415792","0.09208000":"0.30000000","0.09210000":"0.12000000","0.09211470":"0.00500000","0.09211581":"0.00950602","0.09217343":"0.10000000","0.09218600":"0.01064483","0.09220065":"1.00000000","0.09228200":"30.00000000","0.09230000":"0.21668472","0.09233914":"0.00389449","0.09234063":"0.09251583","0.09240000":"0.11531250","0.09243117":"2.99550000","0.09245005":"0.24842726","0.09248459":"5.55674745","0.09249993":"0.00119565","0.09250000":"0.12472032","0.09250156":"0.06223776","0.09261470":"0.00500000","0.09264999":"1.29232259","0.09265181":"0.05000000","0.09266447":"0.10000000","0.09270033":"0.00954804","0.09270901":"20.11314509","0.09273638":"0.02064558","0.09274949":"6.54939660","0.09276001":"0.27727393","0.09290500":"0.00400000","0.09298000":"0.01116893","0.09299898":"0.01500000","0.09299993":"0.00129032","0.09300000":"3.58608852","0.09300054":"0.07523157","0.09300447":"0.10000000","0.09305000":"1.00000000","0.09306008":"0.73204897","0.09309501":"0.11721477","0.09311470":"0.00500000","0.09312000":"0.10738832","0.09312022":"0.00118126","0.09315001":"0.01000092","0.09316138":"0.15000000","0.09325258":"0.09947540","0.09332200":"0.02162280","0.09340000":"0.04050000","0.09340100":"0.40000000","0.09341422":"0.14265513","0.09348657":"0.32357689","0.09348658":"0.32357678","0.09348661":"0.32378617","0.09348906":"0.32388391","0.09348908":"0.32388377","0.09349415":"0.32352410","0.09349993":"0.00129032","0.09350000":"0.00108791","0.09350254":"0.96250020","0.09355210":"0.02476402","0.09361470":"0.00500000","0.09363781":"0.01067945","0.09370000":"30.00000000","0.09373500":"0.03966349","0.09373630":"0.00200000","0.09374000":"2.34832356","0.09374145":"0.00954804","0.09387384":"0.14720924","0.09388500":"1.24000000","0.09389028":"7.24024222","0.09389476":"0.00475204","0.09389775":"0.01000000","0.09399993":"0.00129032","0.09400000":"3.79289619","0.09400447":"0.10000000","0.09409408":"0.78329240","0.09411470":"0.00500000","0.09412592":"1.09356493","0.09420000":"0.70000000","0.09420953":"0.00433349","0.09421492":"0.00158430","0.09423027":"0.30000000","0.09423054":"0.83624604","0.09426494":"0.26013238","0.09431000":"0.10000000","0.09438000":"0.03491259","0.09439926":"0.00704042","0.09439952":"0.03792907","0.09440000":"0.05000000","0.09443113":"0.00529486","0.09443894":"0.01866981","0.09443993":"0.34000000","0.09445056":"0.01091250","0.09449484":"0.40000003","0.09449993":"0.00126984","0.09450000":"0.32797215","0.09452000":"5.00000000","0.09456466":"0.00131238","0.09457831":"0.00567973","0.09460047":"0.00124789","0.09461470":"0.00500000","0.09463483":"0.00269131","0.09468977":"52.80400905","0.09470000":"0.83790000","0.09473000":"0.00105597","0.09475000":"0.40000000","0.09477613":"0.08013514","0.09480000":"13.97900001","0.09480614":"0.03776639","0.09488972":"0.02588209","0.09490000":"0.25000000","0.09491058":"0.69895000","0.09492523":"0.10000000","0.09499900":"0.44099688","0.09499931":"0.13083128","0.09499999":"0.50271382","0.09500000":"21.08020907","0.09503000":"0.50000000","0.09505000":"1.00000000","0.09505362":"0.01142348","0.09508000":"0.30000000","0.09510006":"0.00127070","0.09511470":"0.00500000","0.09512809":"0.83812287","0.09517900":"0.00966155","0.09520000":"0.00106019","0.09523554":"0.04030000","0.09538410":"0.32198878","0.09540000":"0.09611231","0.09547750":"0.00451907","0.09549976":"1.75614696","0.09553587":"0.44978967","0.09560000":"2.50000000","0.09561470":"0.00500000","0.09562811":"0.01103411","0.09566447":"0.10000000","0.09566521":"0.02051431","0.09570000":"0.05123103","0.09572000":"0.31714201","0.09580000":"0.12222679","0.09583819":"0.00399400","0.09584168":"0.03424137","0.09589775":"0.01000000","0.09590000":"0.05170599","0.09593605":"0.10848816","0.09598820":"5.00000000","0.09600000":"2.80179942","0.09600020":"0.13971261","0.09600447":"0.10000000","0.09603033":"0.03938266","0.09604365":"0.00526046","0.09608000":"0.30000000","0.09609500":"0.00437375","0.09610480":"0.03000000","0.09610952":"0.00269931","0.09611470":"0.00500000","0.09614005":"0.01649717","0.09616209":"0.89679147","0.09619439":"0.02368361","0.09620000":"0.06513804","0.09620468":"1.74470666","0.09622000":"0.50000000","0.09622081":"0.01505890","0.09624604":"0.10299257","0.09628750":"0.15590360","0.09640000":"2.31660936","0.09650000":"4.14063490","0.09651569":"0.02588209","0.09654952":"0.03708445","0.09655039":"0.09054001","0.09660000":"0.11029891","0.09660063":"2.11980253","0.09661200":"4.80134611","0.09661470":"0.00500000","0.09666060":"0.00917166","0.09677500":"0.02123445","0.09685000":"0.00104249","0.09690000":"0.01045805","0.09700000":"25.11786823","0.09703690":"0.03260485","0.09705000":"1.00000000","0.09708000":"0.30000000","0.09709800":"0.00109662","0.09711470":"0.00600000","0.09712022":"0.00118126","0.09712407":"0.00114286","0.09712500":"0.02795800","0.09718554":"0.20000000","0.09719609":"0.95956688","0.09721000":"0.46779899","0.09736000":"10.00000000","0.09740000":"0.03880000","0.09741579":"0.08282078","0.09742000":"0.50000000","0.09746079":"0.08282078","0.09746099":"0.08282078","0.09746669":"0.08282078","0.09750000":"0.05434585","0.09750502":"0.15979501","0.09755148":"0.08363346","0.09760000":"4.44106282","0.09761470":"0.00600000","0.09762269":"0.08282078","0.09766447":"0.10000000","0.09768394":"0.10457170","0.09768759":"2.00000000","0.09770000":"0.00228675","0.09770680":"0.01023470","0.09773303":"0.11970000","0.09777000":"0.03305546","0.09779000":"2.05876289","0.09789000":"2.99999999","0.09789775":"0.01000000","0.09790000":"0.00698189","0.09790900":"0.26808480","0.09792012":"0.00322432","0.09796000":"0.11695242","0.09799150":"0.11975999","0.09800000":"2.35211445","0.09801581":"0.00779497","0.09802596":"2.06584578","0.09804362":"0.51440329","0.09810000":"1.00000000","0.09811470":"0.00600000","0.09812760":"5.26323309","0.09814165":"0.02588209","0.09814174":"0.16600847","0.09815000":"10.82605068","0.09815500":"0.01327779","0.09820000":"0.84857500","0.09822165":"0.02265595","0.09822221":"0.23000000","0.09823009":"1.02673656","0.09824761":"0.00112519","0.09825140":"0.00112516","0.09825600":"0.01283803","0.09830000":"0.14964252","0.09834000":"0.30000000","0.09840000":"0.61281654","0.09846105":"0.02751118","0.09850000":"2.23518991","0.09860000":"1.22620762","0.09860320":"0.03013339","0.09861362":"0.00127644","0.09861470":"0.00600000","0.09861573":"0.02413414","0.09864000":"0.50000000","0.09866284":"0.03206530","0.09870000":"1.06187765","0.09870001":"0.10795212","0.09870940":"0.08501134","0.09880000":"0.49896131","0.09880479":"0.17399068","0.09881230":"0.41288277","0.09881820":"0.03623306","0.09882666":"50.59363025","0.09887696":"0.00642750","0.09887810":"0.11970000","0.09889775":"0.01000000","0.09890000":"4.15813014","0.09893861":"0.02625753","0.09895167":"0.01353968","0.09899801":"0.00663771","0.09899839":"0.10782637","0.09899885":"0.63072615","0.09900000":"133.73705206","0.09900800":"0.00121202","0.09903506":"0.31921733","0.09905000":"0.11205892","0.09907210":"0.46779899","0.09910000":"0.01957105","0.09911111":"1.00000000","0.09911206":"0.14977500","0.09911470":"0.00550000","0.09911526":"0.01314653","0.09917422":"0.00111802","0.09917497":"0.02123174","0.09920000":"0.10667028","0.09922110":"26.70731018","0.09922112":"0.20212419","0.09926409":"1.09860812","0.09927651":"0.00866600","0.09929098":"0.29817457","0.09929400":"0.50355500","0.09932016":"2.00749002","0.09933034":"0.03604625","0.09934000":"0.05000000","0.09934054":"0.23489664","0.09937147":"0.50636744","0.09937621":"0.04045589","0.09940000":"1.06986598","0.09940500":"3.28691052","0.09944500":"0.41503918","0.09945969":"0.17757552","0.09949000":"0.02010252","0.09949503":"0.02204037","0.09949635":"0.25738653","0.09950000":"0.07844223","0.09952000":"5.00000000","0.09956525":"0.02186539","0.09958544":"0.00880154","0.09960029":"0.04091354","0.09961470":"0.00500000","0.09970000":"1.07343980","0.09970151":"0.00261341","0.09970170":"2.05156157","0.09972401":"0.10074505","0.09972554":"0.02743067","0.09976762":"0.02588209","0.09976999":"0.01279050","0.09978866":"0.03990000","0.09980000":"0.10000000","0.09980667":"0.00154942","0.09982000":"0.20430302","0.09982802":"0.00180310","0.09987000":"5.50000000","0.09988940":"0.00175288","0.09989029":"0.04016143","0.09990000":"9.49555279","0.09990503":"3.30990527","0.09992595":"0.01574225","0.09994000":"0.02726569","0.09994010":"0.52000000","0.09995000":"0.00200000","0.09998243":"0.71958263","0.09999000":"15.03387533","0.09999100":"0.25648085","0.09999900":"0.06275390","0.09999919":"0.07595347","0.09999998":"0.21945000","0.09999999":"0.00116678","0.10000000":"320.83090700","0.10000001":"0.02830020","0.10000002":"0.02537483","0.10000003":"0.02496250","0.10000004":"0.02435365","0.10000005":"0.02435365","0.10000006":"0.02349412","0.10000007":"0.03524117","0.10000008":"0.02295402","0.10000009":"0.02279555","0.10000010":"0.02258287","0.10000011":"0.02233267","0.10000447":"0.10000000","0.10001230":"0.01759025","0.10010000":"0.00100911","0.10012301":"0.19970568","0.10013000":"0.00248320","0.10015536":"0.20000000","0.10016070":"0.02204037","0.10018569":"0.00997500","0.10019355":"0.01765962","0.10020000":"0.19970000","0.10020114":"0.04050863","0.10022000":"0.04161652","0.10029119":"0.04034685","0.10029809":"1.17551068","0.10030795":"0.01035253","0.10031500":"0.20171732","0.10031760":"0.00207221","0.10036298":"0.09975000","0.10040000":"1.01062756","0.10043944":"0.04000000","0.10048979":"0.50000000","0.10050000":"0.60300717","0.10052472":"0.05003689","0.10054746":"0.02203312","0.10059898":"0.10300000","0.10060000":"0.01878157","0.10061129":"0.03983603","0.10064334":"0.01426027","0.10069000":"0.00106356","0.10069234":"0.01710513","0.10071107":"0.09984999","0.10075000":"0.99710406","0.10079000":"0.01000000","0.10080000":"0.10570312","0.10080467":"0.00992695","0.10082604":"0.05000000","0.10082636":"0.02204037","0.10083900":"0.04165726","0.10089000":"0.00499250","0.10096280":"0.35992779","0.10099950":"0.00200000","0.10100000":"9.19589910","0.10100158":"0.17443750","0.10105917":"0.00455339","0.10106761":"0.03820843","0.10107316":"0.01904951","0.10109900":"0.02000000","0.10112494":"0.03540656","0.10119999":"0.70000000","0.10123027":"0.07730310","0.10124081":"0.10123098","0.10128152":"1.99289572","0.10130000":"0.00110492","0.10133209":"1.25779643","0.10139000":"0.19725811","0.10139358":"0.02588209","0.10140000":"0.05025263","0.10140396":"0.06224707","0.10144413":"0.00492882","0.10144495":"0.00997500","0.10145000":"0.09786012","0.10149202":"0.02204037","0.10149343":"1.00031439","0.10150000":"0.04896268","0.10151549":"0.05089705","0.10152000":"9.06683745","0.10153046":"0.01095316","0.10161408":"0.00991472","0.10163713":"0.37517557","0.10164750":"0.03658725","0.10165192":"0.03522300","0.10168377":"0.04181513","0.10170000":"0.01000000","0.10173903":"0.04004249","0.10174422":"0.33382070","0.10175730":"0.10028078","0.10177659":"0.10024920","0.10178584":"0.11024628","0.10179478":"0.01635548","0.10180896":"0.06171157","0.10187080":"0.05223548","0.10189203":"0.00981431","0.10189707":"0.00498500","0.10190000":"0.10991262","0.10190034":"0.00590640","0.10198822":"0.09569270","0.10199990":"0.39835001","0.10200000":"0.14302513","0.10200045":"0.02766856","0.10210392":"0.10000000","0.10211162":"0.12032117","0.10211376":"0.00100091","0.10212022":"0.00098021","0.10212178":"0.01098285","0.10215769":"0.02204037","0.10220491":"0.03220728","0.10225200":"0.01996000","0.10225485":"0.01000000","0.10230100":"0.01000000","0.10232633":"0.02345691","0.10236609":"1.34584218","0.10238329":"0.03497139","0.10250000":"0.99504782","0.10253391":"0.03492002","0.10257996":"0.74380955","0.10260000":"0.01000000","0.10262043":"0.00107726","0.10263000":"0.03423808","0.10267000":"0.51568540","0.10268580":"0.00902416","0.10268759":"2.00000000","0.10269000":"0.01065736","0.10270000":"0.03680000","0.10274578":"0.00468038","0.10280000":"0.08853008","0.10280719":"0.00156172","0.10281780":"0.52000000","0.10281945":"0.00134585","0.10282335":"0.02204037","0.10290000":"0.10355400","0.10297127":"0.01657826","0.10299107":"0.03118527","0.10299323":"0.00516876","0.10300000":"15.91965753","0.10308670":"0.00195856","0.10309982":"0.00105713","0.10310364":"2.57044588","0.10312971":"0.01087044","0.10318055":"0.72397540","0.10320000":"0.12700000","0.10321000":"0.53220101","0.10325990":"0.00181969","0.10327784":"0.03466848","0.10332001":"0.01304950","0.10332572":"0.48811788","0.10340009":"1.44005113","0.10347390":"0.99750000","0.10350000":"0.14837046","0.10352436":"5.00000000","0.10354511":"0.03953902","0.10360068":"0.02031575","0.10361000":"0.01000000","0.10366068":"0.03454045","0.10366650":"0.03645043","0.10372977":"0.00127298","0.10376237":"0.40031466","0.10379958":"0.01826274","0.10397997":"1.02835983","0.10400000":"0.81951377","0.10400722":"1.00000000","0.10408193":"0.02345691","0.10409900":"0.02500000","0.10410000":"0.15000000","0.10419594":"0.03436301","0.10423192":"0.43661970","0.10426271":"0.02095486","0.10431000":"0.80000000","0.10434990":"0.04000000","0.10438000":"0.01000000","0.10443409":"1.54085471","0.10446478":"0.09572604","0.10449018":"0.01713341","0.10449499":"0.04992500","0.10451500":"0.02457619","0.10452000":"0.01597209","0.10453250":"0.95664000","0.10459860":"0.00453797","0.10468000":"0.12005853","0.10470000":"0.25900000","0.10480000":"0.00731078","0.10488098":"47.67308166","0.10490000":"1.00000000","0.10491902":"0.07929117","0.10499400":"1.25340238","0.10499999":"0.00096190","0.10500000":"4.57490452","0.10500001":"0.10046025","0.10508761":"0.55490000","0.10509802":"8.85279555","0.10511500":"5.00000000","0.10513335":"0.00373191","0.10513637":"0.03760000","0.10520000":"0.21130780","0.10520499":"0.01826274","0.10523057":"0.03248328","0.10531572":"0.29955000","0.10540000":"0.04590000","0.10541145":"0.00434553","0.10545000":"0.02421121","0.10546809":"1.64871454","0.10548261":"0.00795771","0.10550000":"1.00120000","0.10552000":"0.50000000","0.10560049":"0.00111396","0.10562110":"0.39171928","0.10565017":"0.20389496","0.10570000":"2.04133529","0.10575230":"0.10534789","0.10583753":"0.02345691","0.10584839":"0.05132190","0.10595367":"0.47526110","0.10600000":"0.30564729","0.10604344":"0.19360979","0.10611591":"0.47482890","0.10613012":"0.51187656","0.10619467":"0.00941667","0.10620000":"0.49890004","0.10625000":"0.03266595","0.10625821":"0.03369609","0.10627500":"0.00690566","0.10628900":"0.01416839","0.10635088":"0.19223907","0.10640287":"0.33547844","0.10640650":"31.62602994","0.10641500":"0.24938728","0.10650000":"0.10661620","0.10650210":"1.76412456","0.10656291":"0.00094780","0.10659000":"0.03091332","0.10661040":"0.01826274","0.10663579":"0.00111396","0.10670000":"0.03540000","0.10689000":"1.00000000","0.10689895":"0.08916131","0.10690000":"0.00447724","0.10696280":"0.47145677","0.10698000":"0.03994000","0.10700000":"0.63318514","0.10702440":"0.01600000","0.10704000":"0.00998500","0.10707870":"0.50000000","0.10711093":"0.05016825","0.10713600":"0.41800921","0.10716021":"1.10134552","0.10717911":"0.00970191","0.10728431":"0.09659182","0.10730714":"0.00100713","0.10731100":"0.01676620","0.10733106":"0.03199672","0.10737944":"0.03334425","0.10738600":"0.09985000","0.10739105":"0.04992501","0.10739118":"5.00000000","0.10740000":"0.08912750","0.10741970":"0.60000000","0.10748940":"0.00100000","0.10750000":"28.06502832","0.10751000":"0.10007413","0.10751500":"0.10253647","0.10752000":"0.18601190","0.10753610":"1.88761328","0.10757564":"0.00474363","0.10759313":"0.02345691","0.10765769":"0.03325806","0.10767109":"0.00111396","0.10768000":"0.16538522","0.10768759":"2.00000000","0.10770438":"0.09417307","0.10774400":"0.00216606","0.10778469":"0.01702336","0.10780000":"0.30953500","0.10788767":"0.09975000","0.10792000":"0.12354831","0.10796166":"0.51432449","0.10800000":"1.93062667","0.10801581":"0.01826274","0.10806882":"0.01830807","0.10810523":"5.02789128","0.10815544":"0.02356121","0.10822606":"0.25203733","0.10827600":"0.05095410","0.10830000":"0.29606187","0.10837841":"0.00101496","0.10840000":"0.01000000","0.10850000":"0.06928875","0.10851985":"0.00110578","0.10882070":"1.00000000","0.10889100":"0.00092000","0.10892426":"0.01882170","0.10897000":"0.10000000","0.10900000":"3.96793986","0.10903027":"0.02012657","0.10910000":"0.01000000","0.10912022":"0.00091733","0.10925000":"0.15648626","0.10926240":"0.03276961","0.10926408":"0.01733804","0.10934873":"0.02345691","0.10940000":"0.03460000","0.10942122":"0.01826274","0.10948531":"0.46187377","0.10950000":"0.09348641","0.10955590":"0.01995000","0.10957581":"1.72034920","0.10959523":"0.01842591","0.10961701":"0.06686239","0.10971265":"0.00105713","0.10977358":"2.49625005","0.10980000":"4.08117022","0.10984880":"45.51710665","0.10990000":"0.40000000","0.10995010":"0.58494586","0.10996574":"0.99920001","0.10998000":"0.83838352","0.10998510":"0.00099831","0.10999888":"0.19916223","0.10999900":"0.02500000","0.10999998":"0.05075284","0.10999999":"0.09699609","0.11000000":"49.57312437","0.11002883":"0.60010659","0.11008449":"0.04129158","0.11010000":"0.05000000","0.11017001":"0.10095342","0.11020000":"1.00000000","0.11020054":"0.10021238","0.11025000":"0.09664285","0.11025018":"0.07340226","0.11027000":"0.11084604","0.11028000":"0.18135655","0.11028951":"1.29838133","0.11028963":"0.79999854","0.11030000":"0.00508435","0.11050000":"0.02877449","0.11050713":"0.00418938","0.11052139":"1.99999725","0.11057000":"0.50000000","0.11059210":"0.03883000","0.11060000":"0.10493860","0.11061586":"0.00904030","0.11070000":"0.29932150","0.11071001":"0.03204255","0.11074348":"0.01733804","0.11088000":"1.11734891","0.11100000":"6.18790656","0.11100902":"0.10000000","0.11104541":"0.00509647","0.11111111":"0.05822666","0.11111514":"0.09985000","0.11112390":"0.10668606","0.11119094":"0.60085937","0.11130000":"0.31272727","0.11130210":"0.11585065","0.11131897":"0.77727408","0.11133304":"5.75525602","0.11135000":"0.14955000","0.11140000":"0.74990848","0.11141050":"0.20459000","0.11145005":"0.20428029","0.11151396":"1.40000000","0.11159641":"0.03208424","0.11179999":"0.01088440","0.11187661":"0.10594383","0.11200000":"0.65780331","0.11203811":"1.34697781","0.11210000":"1.05105264","0.11210392":"0.10000000","0.11220000":"0.20000000","0.11222075":"0.00185238","0.11222288":"0.01733804","0.11230000":"1.00000000","0.11231000":"6.00000000","0.11235822":"0.79534079","0.11237547":"0.00719496","0.11240000":"0.03000000","0.11245624":"0.04992501","0.11250000":"0.00100000","0.11250100":"0.48144923","0.11261434":"0.01067673","0.11267478":"0.55712288","0.11270000":"0.20000000","0.11274000":"0.10015559","0.11279000":"0.02873772","0.11289069":"0.50000000","0.11294889":"0.11982000","0.11300000":"2.24974192","0.11301600":"0.49116537","0.11310000":"1.50000000","0.11311000":"0.01839812","0.11316138":"0.15000000","0.11320729":"0.01444029","0.11326066":"0.02460342","0.11328357":"0.01506891","0.11336400":"0.02323075","0.11340000":"0.03330000","0.11350000":"0.00798600","0.11356190":"0.14544720","0.11356891":"0.00090000","0.11357465":"0.01500000","0.11358236":"0.51013384","0.11362000":"0.20717075","0.11362309":"0.01118031","0.11370228":"0.01733804","0.11379183":"0.03146523","0.11399050":"0.01779989","0.11400000":"2.24702314","0.11403500":"0.01588581","0.11412022":"0.00091733","0.11423789":"0.05000000","0.11438748":"0.01426429","0.11439000":"0.00174917","0.11464009":"0.00598200","0.11470000":"0.29300000","0.11477230":"0.00997500","0.11477613":"0.06462725","0.11480984":"43.55027030","0.11481242":"0.41566703","0.11486000":"0.16670483","0.11490000":"0.25000000","0.11499999":"0.00087826","0.11500000":"12.26920688","0.11502540":"0.73374982","0.11515670":"0.00868382","0.11518168":"0.01733804","0.11519490":"0.00099700","0.11521043":"0.02795149","0.11536045":"0.00398800","0.11537716":"0.03103288","0.11541359":"0.00104804","0.11550000":"0.09260000","0.11556351":"0.36239825","0.11564500":"0.09664172","0.11568910":"0.00086855","0.11571000":"0.10010162","0.11574751":"0.00593158","0.11575575":"0.00099700","0.11585027":"0.01153167","0.11593168":"0.00199400","0.11599119":"1.00000000","0.11600000":"9.25040975","0.11604541":"0.00509647","0.11612000":"0.50000000","0.11616890":"0.02787570","0.11624393":"0.02323410","0.11624600":"0.00090000","0.11643123":"0.25000000","0.11650544":"0.00199400","0.11660000":"2.00000000","0.11684502":"0.08575635","0.11700000":"0.58504272","0.11740000":"0.03220000","0.11745000":"0.23274012","0.11746000":"0.00090000","0.11750000":"0.00100000","0.11754686":"0.00952171","0.11756000":"0.03226394","0.11756460":"0.00185238","0.11759000":"0.02995500","0.11768001":"1.01039396","0.11768735":"0.04512318","0.11771000":"0.01766484","0.11777000":"50.00000000","0.11800000":"36.81165122","0.11800652":"0.01000000","0.11802088":"0.00876955","0.11812405":"0.01895123","0.11817538":"0.00625363","0.11820000":"20.00000000","0.11821200":"0.03368939","0.11824133":"0.00099700","0.11824600":"0.00090000","0.11826818":"0.03027430","0.11828100":"0.01240843","0.11846065":"0.08451915","0.11849000":"0.10020521","0.11860000":"0.01265815","0.11864500":"1.10261394","0.11866805":"2.06189621","0.11870000":"0.03180000","0.11870570":"0.13380640","0.11882070":"1.00000000","0.11886711":"0.03012176","0.11888000":"0.50000000","0.11888918":"0.08513440","0.11892516":"0.00267336","0.11896287":"0.02000000","0.11900000":"12.31921007","0.11906609":"0.00095966","0.11909025":"0.10972500","0.11910000":"0.10137323","0.11910267":"0.06433841","0.11914632":"0.10554816","0.11926997":"0.00093066","0.11927016":"0.00084682","0.11932101":"0.01243697","0.11932418":"0.01841691","0.11933900":"0.05000000","0.11939572":"0.11937471","0.11945800":"0.06000000","0.11946268":"0.00876955","0.11948590":"0.05000000","0.11949986":"6.52518544","0.11950395":"38.85929407","0.11954720":"0.05866806","0.11968000":"0.16711229","0.11970000":"0.20000000","0.11977204":"0.01455774","0.11980000":"0.78350341","0.11981480":"41.73106814","0.11981827":"0.00834597","0.11982604":"0.05000000","0.11989800":"0.08246482","0.11990000":"2.63794453","0.11990807":"0.17039627","0.11999900":"0.02541250","0.11999990":"0.10158984","0.11999999":"0.00084167","0.12000000":"155.24152222","0.12010150":"1.38291291","0.12024667":"0.00720480","0.12031880":"1.00000000","0.12044844":"0.38100000","0.12046000":"0.00084000","0.12046159":"0.11219812","0.12054351":"0.59548746","0.12059500":"1.00000000","0.12060000":"3.87460710","0.12061009":"0.29816861","0.12061018":"0.29816841","0.12061293":"0.30346486","0.12067483":"0.33576987","0.12070000":"5.09422585","0.12073000":"0.10014279","0.12073400":"1.00000000","0.12080000":"0.53664290","0.12081003":"0.99750001","0.12086000":"0.00338650","0.12092997":"0.83373092","0.12094940":"0.64351324","0.12096771":"0.05491751","0.12100000":"11.97492645","0.12106000":"0.11731636","0.12106533":"0.02739785","0.12110000":"0.05000000","0.12110715":"0.00144637","0.12120000":"0.14202166","0.12121974":"0.00148490","0.12122000":"3.00000000","0.12122885":"0.15022838","0.12140000":"0.33110000","0.12141500":"0.01885285","0.12143328":"0.02063000","0.12146000":"0.00090000","0.12149994":"0.08608877","0.12150000":"0.01194063","0.12164518":"0.01646805","0.12168407":"0.00413027","0.12173300":"0.04800000","0.12180000":"0.17291653","0.12186414":"3.81535230","0.12190000":"0.19966143","0.12193855":"2.06633219","0.12196476":"0.29864454","0.12200000":"2.77564245","0.12207085":"0.01180667","0.12210392":"0.05961000","0.12212022":"0.00081968","0.12213000":"0.20000000","0.12213394":"0.02093681","0.12215000":"0.00090000","0.12218459":"0.12140861","0.12220000":"0.01100000","0.12221350":"1.28410037","0.12225000":"0.00090000","0.12227299":"0.00375690","0.12230000":"0.00844567","0.12235000":"0.00090000","0.12238000":"0.05270798","0.12240000":"0.02033150","0.12240001":"0.29613095","0.12245000":"0.00090000","0.12249499":"0.07186515","0.12249997":"0.00090000","0.12250000":"0.30321050","0.12251850":"0.02504918","0.12252000":"0.14982386","0.12255006":"0.00703770","0.12259800":"0.10000000","0.12264000":"0.10871929","0.12265000":"0.00090000","0.12269997":"0.00090000","0.12270000":"0.03080000","0.12275000":"0.00090000","0.12277300":"0.00821469","0.12279997":"0.00090000","0.12280000":"1.00374103","0.12282440":"0.04246159","0.12285000":"0.00090000","0.12290000":"0.20000000","0.12292426":"0.01836142","0.12295000":"0.00090000","0.12300000":"4.05263859","0.12308486":"0.02379851","0.12310000":"0.04500000","0.12311000":"0.49925000","0.12318444":"0.02379851","0.12328326":"0.02489379","0.12330000":"4.55776802","0.12333000":"0.19489685","0.12338416":"0.85000000","0.12338810":"0.04100000","0.12343152":"0.02131954","0.12345000":"0.01000000","0.12346516":"0.00723830","0.12349000":"0.46632854","0.12350000":"0.51943595","0.12354683":"0.11741361","0.12360000":"0.04992500","0.12369851":"0.69895001","0.12373346":"0.14116018","0.12382010":"1.00000000","0.12386330":"0.10501466","0.12390000":"0.40000000","0.12395798":"0.03511308","0.12400000":"1.33336958","0.12402113":"0.29146577","0.12416000":"0.10738832","0.12420000":"0.10000000","0.12420007":"0.01190813","0.12428502":"0.45757791","0.12429799":"0.02313076","0.12430000":"0.10759215","0.12431619":"0.01168640","0.12432019":"0.16000000","0.12435216":"0.29146577","0.12440000":"0.00196396","0.12444210":"0.10000000","0.12449511":"10.00000000","0.12449999":"0.05000000","0.12450000":"2.99400000","0.12455099":"0.01129187","0.12460000":"0.20300000","0.12460001":"0.16466997","0.12460162":"0.00802558","0.12463529":"2.49537375","0.12480000":"0.80625569","0.12488685":"1.10759318","0.12489814":"40.03261858","0.12497648":"2.00000000","0.12499000":"0.50000000","0.12500000":"31.34955208","0.12502079":"0.02379851","0.12502540":"0.80000000","0.12510010":"0.16520742","0.12520000":"0.50000000","0.12527500":"5.98650000","0.12530000":"0.03020000","0.12535000":"0.01995001","0.12535544":"1.15744083","0.12540000":"0.03111801","0.12550000":"0.23940000","0.12580200":"0.00720497","0.12583000":"0.02125868","0.12591560":"0.07691154","0.12592576":"0.01028553","0.12596000":"0.64281138","0.12599999":"0.00080159","0.12600000":"9.02951350","0.12604475":"0.49585565","0.12606024":"0.21195370","0.12613045":"0.01496250","0.12620000":"0.10000000","0.12645110":"0.04000000","0.12645801":"0.02379851","0.12648893":"0.01509000","0.12650000":"0.13608533","0.12650845":"2.80000000","0.12651992":"0.00279717","0.12654680":"1.32705899","0.12660000":"0.07500000","0.12661501":"0.00335812","0.12664957":"10.80702897","0.12665765":"0.00193058","0.12666509":"1.74022661","0.12667000":"0.29746585","0.12668003":"2.20473407","0.12670000":"0.02980000","0.12676500":"0.01201303","0.12680101":"0.02655854","0.12689000":"1.00000000","0.12695792":"0.29146577","0.12697870":"2.00000000","0.12700000":"0.35838398","0.12700519":"0.17235269","0.12708465":"0.01995000","0.12710000":"0.01856805","0.12713802":"0.67085908","0.12720000":"0.01855345","0.12726655":"0.25000000","0.12730000":"0.01853888","0.12734001":"0.54146029","0.12737498":"0.04000000","0.12740000":"0.01852433","0.12749499":"0.02000000","0.12750000":"1.11932058","0.12758697":"0.00401092","0.12760000":"0.01849529","0.12761900":"0.50000000","0.12764800":"2.00000000","0.12770000":"0.01848081","0.12780000":"0.01846635","0.12783086":"0.00375690","0.12786000":"0.15642109","0.12790000":"0.01845191","0.12791676":"1.32914154","0.12799513":"0.14574713","0.12800000":"40.47431583","0.12800512":"2.35255311","0.12810000":"0.26842310","0.12820000":"25.11840873","0.12829127":"0.21907761","0.12831190":"0.02942589","0.12831339":"0.00111412","0.12835085":"0.50000000","0.12835737":"15.58149719","0.12837370":"0.04762724","0.12840000":"0.01838006","0.12844150":"0.05414246","0.12848288":"2.00000000","0.12850000":"0.12636656","0.12853000":"0.47350871","0.12860000":"0.01835147","0.12870000":"0.01833721","0.12875557":"0.19593054","0.12878000":"0.01474986","0.12880000":"0.01832298","0.12888500":"0.24696838","0.12890000":"0.01830876","0.12900000":"2.17227369","0.12906003":"0.15000000","0.12910000":"0.01828040","0.12916301":"0.00600000","0.12920000":"0.01826625","0.12925485":"0.01000000","0.12930000":"0.24745212","0.12930720":"1.00000000","0.12934872":"0.91234578","0.12937805":"0.00324280","0.12940000":"0.01823802","0.12944500":"0.07988000","0.12950000":"0.01822393","0.12950777":"0.00772154","0.12951000":"1.00000000","0.12952883":"0.02063000","0.12960000":"1.21820987","0.12963172":"1.00000000","0.12967750":"0.00663477","0.12970000":"0.01819583","0.12970700":"0.05000000","0.12980000":"0.01818181","0.12984890":"38.50629166","0.12988999":"0.01592600","0.12989990":"1.00000000","0.12990000":"3.79697992","0.12996000":"28.45250787","0.13000000":"105.57790535","0.13001000":"3.55000000","0.13014018":"0.20014884","0.13026000":"5.26010609","0.13053867":"0.05000000","0.13060000":"0.01521170","0.13063015":"0.00864502","0.13063500":"0.19970003","0.13065000":"3.00000000","0.13065453":"1.68800000","0.13068000":"0.15488215","0.13070000":"0.02890000","0.13070588":"0.01062641","0.13085000":"0.01261000","0.13100000":"0.55481852","0.13119000":"1.42624695","0.13127526":"0.00076747","0.13140000":"4.99250000","0.13142218":"0.53531260","0.13145110":"0.04795989","0.13156400":"0.10983500","0.13190380":"0.04954713","0.13199990":"0.85000000","0.13200000":"0.04813707","0.13207985":"2.80582609","0.13220000":"0.10000000","0.13223250":"0.03581011","0.13226500":"1.49672623","0.13250501":"1.87041741","0.13255000":"0.00431007","0.13259000":"0.00326625","0.13265400":"1.00000000","0.13269997":"0.00406895","0.13270000":"11.01642670","0.13270509":"0.01311569","0.13280000":"25.00000000","0.13286064":"0.00997500","0.13290000":"9.00000000","0.13300000":"1.94197030","0.13301245":"0.16137709","0.13306724":"10.00000003","0.13312022":"0.00075195","0.13320000":"13.02646185","0.13323929":"0.00075803","0.13330000":"0.02830000","0.13333333":"0.24119951","0.13340000":"5.00343116","0.13357001":"1.78771882","0.13362706":"0.49800000","0.13374409":"0.30000000","0.13375800":"0.50000000","0.13377000":"0.00147980","0.13381700":"0.59855702","0.13383770":"0.00131172","0.13393404":"0.83199100","0.13400000":"2.27937441","0.13420000":"0.10000000","0.13435107":"0.01435107","0.13440000":"0.54015115","0.13449999":"0.05000000","0.13450000":"0.01754646","0.13453771":"0.00743286","0.13455590":"0.02000000","0.13456000":"1.00000000","0.13457028":"0.30015673","0.13458440":"0.05000000","0.13461000":"0.04100000","0.13464934":"3.44052877","0.13470000":"0.02810000","0.13479900":"0.00997500","0.13482984":"37.08377633","0.13489990":"1.00000000","0.13497000":"0.31329197","0.13500000":"13.45704002","0.13520000":"0.00849900","0.13545151":"2.36300000","0.13550000":"0.23182039","0.13553867":"0.10000000","0.13555000":"0.03000000","0.13556000":"0.23882517","0.13575000":"1.84651474","0.13580000":"0.01000000","0.13583500":"0.00550387","0.13588888":"3.42518025","0.13592600":"0.74775123","0.13595501":"1.00000000","0.13598001":"1.60000000","0.13598660":"0.14954400","0.13599930":"1.00000000","0.13600000":"14.41773742","0.13600984":"0.10621308","0.13601500":"0.07831213","0.13620000":"0.10000000","0.13627549":"0.02000000","0.13632000":"0.08556493","0.13645000":"0.02000000","0.13650000":"0.09638937","0.13661860":"0.03689903","0.13681000":"1.00000000","0.13700000":"0.00775193","0.13715000":"0.03847000","0.13730000":"0.02750000","0.13738711":"0.22067385","0.13750000":"1.06716363","0.13753000":"0.35000000","0.13762439":"0.02065710","0.13777000":"2.00000000","0.13784123":"0.33261107","0.13797015":"2.02164013","0.13800000":"0.29784446","0.13801493":"0.82179763","0.13815910":"0.05824446","0.13820000":"0.10000000","0.13840002":"0.05613856","0.13840337":"28.70423164","0.13840997":"0.03000000","0.13850000":"0.01703971","0.13858609":"0.10972500","0.13870000":"0.02730000","0.13870570":"0.10000000","0.13872138":"0.51143309","0.13876706":"0.02090443","0.13880000":"0.00500000","0.13881459":"0.00714241","0.13890000":"0.01000000","0.13899552":"0.05000000","0.13900000":"1.53259728","0.13910915":"0.00719934","0.13929876":"0.01449354","0.13930000":"0.75000000","0.13934000":"0.04000000","0.13938899":"0.00997500","0.13942084":"0.17764552","0.13944600":"0.94597819","0.13949788":"2.00000000","0.13950000":"0.04954906","0.13955500":"0.08973911","0.13959165":"0.00081977","0.13960000":"8.00000000","0.13969241":"0.00715858","0.13972399":"0.84980637","0.13977044":"0.50000000","0.13979700":"0.15008820","0.13983482":"35.75647069","0.13985523":"0.06508622","0.13989000":"3.72984442","0.13989990":"1.00000000","0.13990000":"0.99639255","0.13991704":"0.04251787","0.13999900":"0.09324583","0.14000000":"71.45630775","0.14000001":"0.00755827","0.14000029":"0.00640166","0.14021001":"0.00792863","0.14033400":"0.00997500","0.14040000":"0.08500000","0.14050000":"0.07619296","0.14060000":"0.07244009","0.14069999":"0.02094713","0.14072500":"0.00071066","0.14080000":"0.29955000","0.14083000":"0.01885285","0.14083001":"0.00326618","0.14086895":"0.35000000","0.14087007":"0.59412531","0.14100000":"0.99158876","0.14100902":"0.12238308","0.14110010":"2.39019194","0.14121844":"0.00644820","0.14130000":"0.02670000","0.14140000":"0.02624420","0.14142395":"42.48936173","0.14147000":"0.08243544","0.14169451":"0.07193804","0.14177503":"0.40179320","0.14179999":"0.08892158","0.14182418":"5.00000000","0.14191110":"0.00142346","0.14191672":"5.33069002","0.14200000":"9.01728363","0.14200037":"0.01314758","0.14202299":"0.39812218","0.14220758":"0.50905612","0.14225000":"0.63895091","0.14228610":"0.00359296","0.14237000":"1.00000000","0.14246951":"1.44500000","0.14247500":"0.00431014","0.14250000":"0.00998500","0.14255202":"0.97979656","0.14260000":"0.03599027","0.14261146":"0.00126217","0.14268388":"0.12954539","0.14270000":"0.02650000","0.14273010":"0.01454489","0.14274409":"0.46000000","0.14277502":"0.90876795","0.14280000":"30.00000000","0.14289900":"0.00997500","0.14295000":"0.33277963","0.14295873":"0.00189525","0.14300000":"44.18890963","0.14300010":"0.11206228","0.14301550":"0.00997500","0.14316138":"0.15000000","0.14318824":"5.00000000","0.14320000":"4.01821746","0.14332828":"0.06609464","0.14336000":"0.18601190","0.14340000":"0.00597655","0.14349999":"0.00430111","0.14350000":"0.00593448","0.14370000":"0.00131644","0.14372100":"4.33011244","0.14380000":"7.92993901","0.14387499":"0.34917736","0.14390000":"0.20000000","0.14400000":"8.45471184","0.14400711":"0.01885440","0.14420886":"0.37088035","0.14440000":"0.13500000","0.14440557":"0.20514420","0.14442750":"0.00997500","0.14444000":"0.04000000","0.14445677":"0.50000000","0.14449999":"0.05000000","0.14450000":"1.30000000","0.14452160":"11.42408361","0.14455590":"0.02000000","0.14458440":"0.05510526","0.14464644":"0.09985000","0.14470000":"0.05000000","0.14481000":"0.00236483","0.14483983":"34.52088873","0.14485000":"0.00652720","0.14486000":"0.10000000","0.14489534":"0.01760305","0.14490000":"0.62217527","0.14497281":"0.00689785","0.14497800":"0.01865879","0.14500000":"17.96278636","0.14500090":"0.44147681","0.14501950":"0.01034343","0.14510596":"0.30104097","0.14514381":"0.15507012","0.14516500":"1.00000000","0.14521000":"0.66186537","0.14530000":"0.02600000","0.14530411":"0.04992500","0.14531818":"0.01227150","0.14532110":"0.48891415","0.14540000":"0.31381746","0.14555499":"0.00866464","0.14560003":"0.00078534","0.14560020":"0.25000000","0.14564987":"0.00145349","0.14566000":"0.02649328","0.14567800":"1.00000000","0.14591033":"2.00000000","0.14592663":"0.19950000","0.14592948":"0.00068595","0.14600000":"0.92536553","0.14602620":"0.22241656","0.14615270":"0.01313189","0.14638000":"8.96803312","0.14647500":"2.18390000","0.14660000":"0.32475122","0.14670000":"0.02580000","0.14670402":"0.07480553","0.14691033":"2.00000000","0.14700000":"2.32052800","0.14702569":"0.05000000","0.14704000":"0.18135655","0.14714849":"0.00997500","0.14720000":"0.01000000","0.14731910":"0.37314283","0.14746004":"6.88965000","0.14749739":"3.79595400","0.14750000":"0.09459335","0.14752884":"0.01124875","0.14800000":"5.30117354","0.14819160":"1.99700000","0.14829879":"0.00631306","0.14842000":"1.00000000","0.14849000":"0.00407975","0.14850000":"0.06839042","0.14870000":"6.05300000","0.14870570":"0.10000000","0.14880000":"0.99911452","0.14890000":"0.10564961","0.14897578":"1.12170049","0.14900000":"5.01944078","0.14902800":"0.20000000","0.14908386":"0.74237912","0.14930000":"0.02530000","0.14941218":"0.00106645","0.14943000":"1.00000000","0.14956689":"0.01892109","0.14970000":"0.20852935","0.14971354":"0.00111315","0.14975000":"0.20000000","0.14978000":"1.72856217","0.14979000":"0.01000000","0.14984839":"33.36705631","0.14985687":"6.88705389","0.14995000":"0.05000000","0.14995014":"1.00000000","0.14998019":"0.50000000","0.14998989":"40.00269618","0.14999002":"0.20973542","0.14999900":"0.03609309","0.14999980":"30.00000000","0.14999999":"0.19022715","0.15000000":"111.14746160","0.15000001":"0.69999998","0.15004618":"0.03249287","0.15010000":"0.01000000","0.15019897":"0.05245208","0.15020000":"1.31312028","0.15033932":"0.00985329","0.15037000":"0.00559915","0.15037981":"0.00664983","0.15050000":"0.00167902","0.15053325":"0.16796919","0.15064075":"0.00133007","0.15070000":"0.02510000","0.15072809":"0.15000000","0.15073889":"0.01535831","0.15090000":"0.05000000","0.15092636":"1.23181869","0.15100000":"12.18448944","0.15101015":"0.00069500","0.15102604":"0.00537981","0.15140000":"1.02585617","0.15145000":"1.50000000","0.15150000":"0.03985279","0.15160000":"2.94210482","0.15170514":"0.00500000","0.15173441":"7.07635045","0.15175000":"30.10771200","0.15179791":"0.07283776","0.15199900":"1.48405104","0.15200000":"0.66510672","0.15212000":"0.00672062","0.15222198":"0.50459917","0.15230000":"0.15266350","0.15247470":"0.02649295","0.15250000":"3.49805607","0.15280000":"35.00000000","0.15281000":"0.10000000","0.15296640":"0.00071690","0.15300000":"0.00697196","0.15316510":"0.01321681","0.15330000":"0.02470000","0.15340000":"0.02925905","0.15347681":"6.65139524","0.15349919":"0.05164980","0.15350000":"0.06848261","0.15353761":"9.98500000","0.15370000":"0.00130893","0.15382880":"0.15000000","0.15399999":"2.23546279","0.15400000":"1.62893907","0.15400001":"1.67720199","0.15420000":"0.24553276","0.15449999":"12.15678883","0.15462174":"0.03652092","0.15470000":"0.02440000","0.15489848":"32.27920428","0.15498989":"23.24039935","0.15500000":"7.71518924","0.15500001":"0.27100000","0.15511100":"0.01744123","0.15520005":"0.00900000","0.15529326":"0.21744768","0.15540000":"0.05242594","0.15559050":"0.02460857","0.15591431":"0.00641378","0.15598800":"0.00138333","0.15599930":"1.00000000","0.15600000":"0.20045775","0.15600001":"0.21706521","0.15620818":"0.72797520","0.15639814":"0.05000001","0.15681235":"0.36709559","0.15700000":"1.50680272","0.15730000":"0.02400000","0.15743488":"0.09985000","0.15750000":"0.06400000","0.15752000":"2.11746294","0.15762772":"0.02000000","0.15770000":"0.00600000","0.15780000":"0.24096283","0.15800000":"0.00736581","0.15846796":"0.03000000","0.15850000":"0.00864491","0.15853000":"0.01927868","0.15860000":"0.02380000","0.15888888":"0.10000000","0.15899993":"0.00104260","0.15900000":"1.55671140","0.15909276":"0.12974000","0.15925405":"0.01000000","0.15948984":"31.34995738","0.15949490":"0.05000000","0.15957497":"0.30000000","0.15976997":"6.00000000","0.15989845":"0.01438413","0.15991201":"0.99928896","0.15995000":"0.04985000","0.16000000":"21.45155242","0.16010000":"1.50000000","0.16010001":"0.50000000","0.16024964":"0.00063027","0.16028596":"0.67000000","0.16050000":"0.00934579","0.16073268":"0.00714241","0.16100000":"0.00719424","0.16147558":"2.72191618","0.16151266":"0.11975999","0.16157716":"0.00618899","0.16188000":"0.12354831","0.16189125":"0.35377860","0.16190000":"3.98500000","0.16200000":"1.00849328","0.16203890":"0.01410722","0.16238453":"0.16770526","0.16276999":"0.18981000","0.16280000":"30.00000000","0.16285328":"2.04126348","0.16300000":"0.00729927","0.16318194":"0.10000000","0.16400000":"0.00859983","0.16449999":"0.07089333","0.16452100":"5.00000000","0.16466803":"2.75536306","0.16473000":"0.50000000","0.16485948":"30.32885763","0.16500000":"3.15988842","0.16500100":"0.30000000","0.16524901":"0.00286901","0.16550000":"0.02239847","0.16557879":"0.20059622","0.16568376":"0.04599998","0.16600000":"0.18141208","0.16649230":"0.01410260","0.16653020":"13.00000000","0.16718283":"0.11970000","0.16736922":"0.00597481","0.16750000":"0.00149253","0.16777777":"0.59602649","0.16800000":"0.03124689","0.16803566":"0.11970000","0.16820000":"0.11970000","0.16832300":"0.22690900","0.16870570":"0.10000000","0.16875000":"0.42500000","0.16880000":"0.30033173","0.16885808":"29.61066477","0.16888888":"0.10000000","0.16900000":"0.05499250","0.16919983":"0.11970000","0.16925400":"0.17780189","0.16930000":"3.00000000","0.16949000":"0.00059009","0.16964528":"0.02000000","0.16976997":"6.00000000","0.16979003":"0.05172406","0.16997050":"0.11970000","0.16999900":"0.05000000","0.17000000":"4.67799042","0.17000001":"0.07191201","0.17004900":"0.28499955","0.17013559":"0.12258726","0.17048000":"0.15642109","0.17050130":"1.00848500","0.17050505":"0.00253365","0.17110002":"0.33858881","0.17200000":"0.00124689","0.17211133":"0.07445443","0.17227000":"29.67561759","0.17249849":"0.43260956","0.17329128":"0.00577063","0.17352583":"0.11970000","0.17387440":"1.49987844","0.17400000":"0.00124689","0.17424000":"0.15304561","0.17440000":"3.23930177","0.17456000":"0.00995500","0.17466530":"2.96112636","0.17467977":"0.01035115","0.17480259":"28.60369354","0.17500000":"3.10656046","0.17521300":"0.17973029","0.17562267":"0.04400001","0.17600000":"10.00124689","0.17692509":"0.10972500","0.17739698":"1.12331250","0.17760000":"1.00000000","0.17770000":"0.01300000","0.17799000":"0.02000000","0.17799671":"0.21551144","0.17800000":"4.02377066","0.17884802":"27.95669598","0.17887212":"4.00000000","0.17888880":"0.10000000","0.17899993":"0.12980500","0.17900000":"0.05000000","0.17934413":"0.00557587","0.17971001":"0.07727524","0.17993995":"0.00500000","0.17997697":"4.00000000","0.17999990":"0.00253854","0.17999999":"0.07000000","0.18000000":"33.93239228","0.18200000":"30.00124689","0.18240500":"0.01101334","0.18254698":"0.00054900","0.18265078":"0.00714241","0.18299000":"0.00433900","0.18396000":"0.10871929","0.18400000":"0.00124689","0.18400001":"0.12087515","0.18442500":"0.15252597","0.18450000":"0.04593125","0.18455555":"1.00000000","0.18466390":"1.62309433","0.18473000":"0.50000000","0.18478848":"27.05796233","0.18484029":"1.50000000","0.18500000":"1.01500000","0.18528914":"0.11674959","0.18543000":"2.34995463","0.18552855":"0.00539001","0.18580011":"20.00000000","0.18595457":"0.00675408","0.18600000":"0.00124689","0.18624000":"0.10738832","0.18667999":"6.38381646","0.18675000":"0.00113673","0.18675241":"0.04199999","0.18690875":"0.13916377","0.18700000":"0.15092225","0.18720767":"1.99021784","0.18770000":"0.05000000","0.18776997":"6.00000000","0.18777777":"0.53254438","0.18800000":"0.00124689","0.18880000":"0.00079800","0.18888880":"0.10000000","0.18900000":"0.05000000","0.18910100":"5.29229760","0.18932298":"0.43546927","0.18947884":"26.38816945","0.18949490":"0.05153542","0.18957956":"0.00664628","0.18977613":"0.07000000","0.19000000":"5.73579316","0.19010831":"10.00000000","0.19030616":"0.00470000","0.19163004":"0.05442915","0.19174800":"0.04992500","0.19184528":"0.00521253","0.19200000":"0.00124689","0.19230080":"0.04000000","0.19257150":"0.03990000","0.19290010":"33.54529642","0.19297994":"17.38426744","0.19340003":"0.05894024","0.19393300":"5.00000000","0.19400000":"0.01124689","0.19440000":"0.11300000","0.19449999":"0.05000000","0.19462007":"0.08427245","0.19473000":"1.00000000","0.19485900":"0.05000000","0.19494788":"25.64787955","0.19500000":"1.00000000","0.19599600":"0.08771546","0.19600000":"1.05634893","0.19670000":"0.00998500","0.19673799":"6.14516633","0.19691031":"0.92572112","0.19751799":"0.00192109","0.19780000":"0.17000000","0.19800000":"0.00124689","0.19824997":"0.00200100","0.19829504":"0.00504299","0.19881000":"0.49925000","0.19881564":"0.04000002","0.19900000":"0.05000000","0.19920201":"0.24809239","0.19949478":"25.06331118","0.19999698":"0.50000000","0.19999999":"1.07563615","0.20000000":"46.21030415","0.20000400":"0.02630687","0.20020000":"5.00000000","0.20122808":"0.00439998","0.20149980":"0.09975000","0.20152000":"10.00000000","0.20170380":"0.00201587","0.20200000":"0.00124689","0.20235000":"0.49950000","0.20270890":"0.63900000","0.20400000":"0.00124689","0.20456887":"0.00714241","0.20462000":"1.21035607","0.20487852":"0.00488094","0.20488025":"24.40449852","0.20500000":"0.00500000","0.20600000":"0.00124689","0.20673799":"4.35000000","0.20797200":"10.42936396","0.20800000":"0.00124689","0.20856320":"0.02157619","0.20885793":"0.02237690","0.20900000":"0.12000000","0.20948802":"23.86771216","0.21000000":"5.11063576","0.21150000":"0.00200000","0.21159641":"0.00472598","0.21189797":"0.03799998","0.21200000":"0.00124689","0.21235300":"1.88512217","0.21244688":"0.04561500","0.21249536":"0.05000000","0.21340108":"0.00409997","0.21400000":"0.00094392","0.21473000":"1.00000000","0.21473799":"4.30000000","0.21489488":"23.26718891","0.21500000":"0.70000000","0.21584000":"0.12354831","0.21600000":"2.99650878","0.21748590":"0.03000000","0.21797996":"4.35000000","0.21800000":"0.00337117","0.21844936":"0.00457772","0.21888880":"0.45685297","0.21894880":"22.83638811","0.21897368":"0.33312910","0.21900000":"0.37275000","0.22000000":"10.06730212","0.22190000":"0.04265331","0.22200000":"0.00338294","0.22222222":"0.88362824","0.22273599":"1.14124105","0.22400000":"0.00338009","0.22489488":"22.23260831","0.22500000":"0.03000000","0.22543801":"0.00443581","0.22645568":"0.03599998","0.22648696":"0.00714242","0.22740000":"0.02982525","0.22800000":"30.51572391","0.22880858":"0.00379998","0.22894894":"21.83892960","0.22900000":"0.05000000","0.22995225":"0.01994000","0.23256298":"0.00429991","0.23473000":"1.00000000","0.23482894":"21.29209368","0.23848532":"1.68025853","0.23894828":"20.92502943","0.23900000":"0.05000000","0.23982486":"0.00416971","0.24000000":"0.33621999","0.24070720":"0.06669369","0.24182418":"5.00000000","0.24221403":"0.03400001","0.24318849":"4.99500001","0.24390010":"30.00000000","0.24435256":"0.00340000","0.24483894":"20.42158734","0.24500040":"2.65619743","0.24528000":"0.10871929","0.24667328":"0.00045000","0.24722423":"0.00404491","0.24777777":"0.40358744","0.24832000":"0.10738832","0.24885793":"0.03000000","0.24889000":"3.00000000","0.24889775":"0.10000000","0.24900000":"0.05000000","0.25000000":"42.35645600","0.25078490":"0.05000000","0.25105743":"4.39997108","0.25150000":"0.00200000","0.25185152":"0.00514276","0.25278000":"0.69895000","0.25399679":"2.00000000","0.25476165":"0.00392524","0.25500000":"0.50000000","0.25589000":"0.00697297","0.25622530":"0.00604277","0.25681496":"0.00413846","0.25900000":"0.05000000","0.25954820":"0.03199999","0.26000000":"0.04405246","0.26024598":"11.60873204","0.26105680":"0.00397381","0.26243767":"0.00381043","0.26318999":"0.17263558","0.26367467":"0.00299998","0.26507849":"0.05000000","0.26690000":"0.45180000","0.26755000":"4.20000000","0.26900000":"0.05000000","0.26917018":"0.03000000","0.27000000":"1.52218032","0.27025280":"0.00370024","0.27061800":"2.77144268","0.27390010":"20.00000000","0.27474704":"0.08277851","0.27570007":"0.03767063","0.27650784":"0.05000000","0.27700000":"2.87837328","0.27776130":"0.04071570","0.27820755":"0.00359444","0.27900000":"0.05000000","0.28000000":"10.67141709","0.28150000":"0.00300000","0.28275312":"2.00000000","0.28280000":"27.80052016","0.28284791":"21.24468086","0.28289114":"1.07409933","0.28483695":"0.00270000","0.28630242":"0.00349281","0.28637648":"0.90099540","0.28765078":"0.04881565","0.28882875":"0.01995000","0.28888880":"0.34615395","0.28900000":"0.05000000","0.29000000":"0.00139511","0.29200000":"0.11538835","0.29245454":"0.05000007","0.29453787":"0.00339515","0.29500000":"2.16720000","0.29530980":"0.01987147","0.29637648":"1.00000000","0.29800000":"1.69214686","0.29900000":"1.00467775","0.29970100":"0.00300000","0.29999900":"1.00000000","0.30000000":"15.92541655","0.30221420":"0.00036728","0.30265465":"0.50000000","0.30291436":"0.00330126","0.30292911":"1.84263363","0.30637648":"1.00000000","0.30900000":"0.12000000","0.31000000":"5.06295713","0.31143234":"0.00321097","0.31245454":"0.05000007","0.31447750":"0.00240001","0.31637648":"1.00000000","0.31655000":"0.00431915","0.31900000":"0.05000000","0.32000000":"0.06641610","0.32637648":"1.00000000","0.32800000":"46.68429950","0.32960000":"9.31931600","0.33060000":"0.38958241","0.33280168":"0.33280168","0.33340000":"6.00000000","0.33637648":"1.00000000","0.34055000":"1.00000000","0.34473000":"1.00000000","0.34637648":"1.00000000","0.34885793":"0.02000000","0.35000000":"0.40000000","0.35637648":"1.00000000","0.35700000":"0.02647901","0.35793500":"0.00031011","0.36637648":"1.00000000","0.37000000":"0.49900000","0.37637648":"1.00000000","0.38828000":"50.00000000","0.39248121":"0.00028281","0.39600004":"1.20000000","0.40000000":"12.34555388","0.40900000":"0.01744356","0.41899100":"0.00026492","0.42885990":"0.00357829","0.42906810":"0.00025871","0.43000000":"0.01146596","0.43888888":"0.22784810","0.44473000":"1.00000000","0.44964644":"1.00000000","0.45500000":"0.30000000","0.47793131":"0.00023226","0.48000000":"0.01020276","0.48280000":"109.90319469","0.48554620":"0.03792183","0.49000000":"4.41113744","0.49249264":"0.04465203","0.49500000":"2.00000000","0.49899490":"0.00022244","0.50000000":"22.14493397","0.51327180":"0.00373294","0.52535000":"0.00021128","0.53795003":"1.00000000","0.54473000":"1.00000000","0.55468000":"0.00020011","0.55500000":"0.50000000","0.58112070":"0.10000000","0.58830030":"0.72500000","0.58832390":"0.00018867","0.60000000":"0.74095075","0.61080100":"0.00018172","0.61279990":"1.74434023","0.63446989":"0.44249357","0.63851000":"0.00929285","0.64150000":"0.00017303","0.64730000":"1.00000000","0.65000000":"0.30000000","0.65888888":"0.30354131","0.66455020":"0.00016703","0.66666666":"0.04080688","0.67777770":"4.94978580","0.68775010":"0.00016139","0.68888888":"5.13949362","0.69999999":"4.97950728","0.70000000":"0.68455275","0.71480000":"0.07699578","0.71850025":"0.41952015","0.72300000":"0.01999462","0.72590020":"0.00015291","0.73775010":"1.14880974","0.74500000":"2.00000000","0.74700400":"0.20900019","0.75000000":"0.45381243","0.76551230":"0.00400000","0.76888190":"0.00154049","0.77000000":"0.34455224","0.80000000":"0.79487747","0.83700000":"0.01997000","0.84643808":"1.00000000","0.84730000":"2.00000000","0.85000000":"0.30000000","0.87745501":"0.24168029","0.87888888":"8.04623220","0.88425001":"0.00012002","0.89000000":"0.28872521","0.90000000":"2.82396143","0.91000000":"0.00995589","0.94730000":"2.00000000","0.94964644":"1.00000000","0.95000000":"0.30000000","0.96424250":"0.01200000","0.97000000":"1.00000000","0.97799990":"0.01000000","0.97949720":"0.09000000","0.98000000":"0.85628262","0.99000000":"0.52793810","0.99000020":"0.20000000","0.99500000":"1.00000000","0.99900000":"0.21441306","0.99999998":"1.88673282","0.99999999":"2.97890914","1.00000000":"32.39198203","1.02200499":"1.61425538","1.07530000":"0.15000000","1.09880480":"20.09063444","1.10000000":"0.15466832","1.18956449":"0.01917406","1.20000000":"0.22349025","1.30000000":"0.44964486","1.30199353":"1.53651820","1.52300000":"0.00669289","1.59066526":"0.01000000","1.60000000":"0.06197573","1.66666666":"1.00724564","1.83901004":"12.97894124","1.84643808":"1.00000000","1.94730000":"1.00000000","2.00000000":"0.92918454","2.14010402":"0.06925027","2.22222222":"4.95020160","2.45597765":"0.01000000","2.50000000":"2.68557693","3.08952500":"0.50000000","3.20000000":"2.23960244","3.55000505":"4.95061740","3.55555555":"4.95228060","4.00000000":"0.00027500","4.08237033":"0.02801567","4.44444444":"4.94978580","4.93891000":"0.00285286","5.00000000":"2.30051373","5.08299899":"0.01793293","5.94750146":"0.50000000","6.00000000":"1.00000000","6.93333333":"4.95648880","7.00000000":"1.30000000","7.96424250":"0.01288805","8.00000000":"1.00026250","9.00000000":"1.00000000","9.54650098":"0.01000000","9.70000000":"1.00000000","10.00000000":"2.50170455","11.70735686":"0.00081917","12.17500103":"0.00082135","12.17846784":"0.00082112","12.22535581":"0.00081797","15.00000000":"0.30000000","15.94750146":"0.50000000","16.00000000":"0.00019375","20.00000000":"1.00000000","24.97583057":"0.01000000","25.00000000":"0.30000000","32.00000000":"0.00012813","34.00000000":"0.10000000","38.00000000":"0.00322360","50.00000000":"1.00000000","64.00000000":"0.00006266","77.38900000":"0.01000000","84.21800000":"0.00249400","96.35001000":"0.00000234","99.00000000":"0.15000000","100.00000000":"1.10000000","115.94750146":"0.50000000","130.00000000":"0.00003085","197.00000000":"2.00000000","260.00000000":"0.00001543","475.13465857":"0.01500000","520.00000000":"0.00000772","780.00000000":"0.20000000","999.00000000":"0.20000000","1000.00000000":"0.00103379","1000.02022945":"1.00000000","1000.17618025":"0.00100000","1148.00000000":"0.04594689","1997.00000000":"2.00000000","2000.00000000":"0.00000206","3000.00000000":"0.00000137","3772.00000000":"0.65977073","4000.00000000":"0.00000103","5000.00000000":"0.10284089"},{"0.02310611":"21.20361406","0.02310610":"6.68324293","0.02310609":"4.00000000","0.02310602":"2.18632904","0.02310600":"83.88440000","0.02310576":"85.00000000","0.02308342":"3.41194800","0.02306799":"8.00000000","0.02306796":"0.70170097","0.02306400":"5.16659306","0.02306395":"0.00596558","0.02306050":"1.21419744","0.02304842":"0.01189382","0.02304128":"0.02170018","0.02303636":"0.04775060","0.02303635":"0.08985799","0.02303184":"18.29000000","0.02302641":"0.01594362","0.02302407":"0.01209088","0.02300986":"0.59849633","0.02300041":"0.00573903","0.02300000":"18.90503189","0.02298903":"60.57000000","0.02298495":"0.55500003","0.02298317":"56.49775139","0.02297730":"0.00621588","0.02297480":"0.00860000","0.02297456":"0.01189382","0.02295038":"2.52305473","0.02294923":"1.27669578","0.02294920":"0.00599546","0.02294396":"0.05498811","0.02293713":"586.54000000","0.02292989":"17.04080463","0.02292988":"0.04361121","0.02292500":"0.22107450","0.02292491":"0.02181034","0.02292001":"0.05017450","0.02292000":"0.09620419","0.02290070":"0.01189382","0.02290000":"6.00000000","0.02289674":"0.06571171","0.02288425":"0.00624884","0.02288000":"163.40463321","0.02287368":"1.22411436","0.02287003":"0.55500004","0.02286000":"0.00500000","0.02285900":"0.00950063","0.02285000":"7.22107450","0.02284584":"0.00485865","0.02283700":"0.59849633","0.02283502":"0.00602532","0.02282684":"0.01189382","0.02280367":"0.05262311","0.02280366":"0.10261511","0.02278000":"2.00000000","0.02277500":"0.22107450","0.02277463":"11.29396482","0.02276809":"0.00676386","0.02276166":"0.05492789","0.02275568":"0.55500005","0.02275298":"0.01189382","0.02274692":"302.63000000","0.02272141":"0.00605574","0.02270000":"11.22596436","0.02269422":"0.22032041","0.02268732":"0.05509686","0.02268731":"0.10909183","0.02268000":"4.00000000","0.02267912":"0.01189382","0.02267775":"175.57000000","0.02267333":"0.00500000","0.02266543":"0.59849633","0.02265900":"0.12864910","0.02265192":"0.00728416","0.02264190":"0.55500006","0.02263528":"0.06571171","0.02262933":"0.02377825","0.02262500":"0.22107450","0.02260836":"0.00608560","0.02260526":"0.01189382","0.02260000":"4.00000000","0.02257230":"2.22181809","0.02257098":"0.05759609","0.02257097":"0.11563527","0.02256588":"0.02869842","0.02255000":"0.22107450","0.02254385":"0.14110012","0.02253576":"0.00780981","0.02253321":"119.34000000","0.02253140":"0.01189382","0.02253000":"5.00000000","0.02252869":"0.55500007","0.02250000":"18.85347779","0.02249588":"0.00611602","0.02249515":"0.59849633","0.02248666":"0.00500000","0.02248000":"0.00493772","0.02247500":"0.22107450","0.02245754":"0.01189382","0.02245698":"1.11412131","0.02244206":"0.06015312","0.02243992":"0.05310000","0.02243186":"0.10510096","0.02241786":"0.05000000","0.02241605":"0.55500008","0.02241595":"0.10074969","0.02240130":"0.05000000","0.02240100":"0.01071381","0.02240000":"5.23566379","0.02238467":"0.90797261","0.02238396":"0.00614698","0.02238368":"0.01189382","0.02237698":"0.63312163","0.02237383":"0.06571171","0.02236391":"0.88417429","0.02235587":"0.05000000","0.02233010":"0.05544087","0.02232615":"0.59849633","0.02232500":"0.22107450","0.02231034":"0.28013916","0.02230982":"0.01189382","0.02230886":"0.05310000","0.02230769":"0.03441200","0.02230630":"1.03689003","0.02230400":"1.04147597","0.02230397":"0.55500009","0.02230390":"9.93529472","0.02230000":"11.00948431","0.02227259":"0.00617738","0.02227109":"0.05030075","0.02226251":"0.05560919","0.02226000":"0.00498653","0.02225000":"0.22107450","0.02223596":"0.01189382","0.02221312":"0.05000000","0.02220100":"0.01081033","0.02220007":"1.05210930","0.02220000":"11.03168423","0.02219491":"0.05577856","0.02219351":"0.05000000","0.02219245":"0.55500010","0.02218276":"0.00494168","0.02217500":"0.22107450","0.02216829":"0.05921791","0.02216210":"0.01189382","0.02216178":"0.00620834","0.02215841":"0.59849633","0.02215279":"0.05000000","0.02215000":"0.00902935","0.02214275":"0.06800000","0.02212731":"0.05594897","0.02211237":"0.06571171","0.02210700":"0.05000000","0.02210000":"12.02704509","0.02209310":"0.00677973","0.02208149":"0.55500011","0.02207692":"0.03441200","0.02207220":"7.06771414","0.02205971":"0.05612042","0.02205152":"0.00623930","0.02205000":"25.00000000","0.02204544":"0.00503505","0.02202786":"2.26985193","0.02202500":"0.22107450","0.02202000":"0.04528020","0.02201232":"1.00000000","0.02201000":"0.02057701","0.02200000":"28.91081357","0.02199194":"0.59849633","0.02197108":"0.55500012","0.02195001":"0.00618633","0.02195000":"0.22107450","0.02194181":"0.00627084","0.02194016":"0.06583622","0.02190001":"0.01506849","0.02190000":"10.04899443","0.02188891":"0.05165706","0.02187500":"0.22107450","0.02187244":"0.03400000","0.02187190":"0.25146413","0.02186122":"0.55500013","0.02185376":"0.20000000","0.02185092":"0.06571171","0.02184795":"1.00000000","0.02184615":"0.03441200","0.02183847":"0.84955539","0.02183264":"0.00630238","0.02182672":"0.59849633","0.02180999":"25.10000000","0.02180100":"0.01032063","0.02180000":"8.24419836","0.02179599":"4.58799859","0.02179570":"59.21000000","0.02178747":"0.00880783","0.02178623":"0.05000000","0.02178526":"0.05000000","0.02176000":"0.03000000","0.02175608":"1.00000000","0.02175191":"0.55500014","0.02175007":"0.03400000","0.02174720":"1.00000000","0.02172723":"0.13807604","0.02172401":"0.00633334","0.02170100":"0.01036819","0.02170037":"7.00000000","0.02170000":"6.05667373","0.02169971":"0.36002785","0.02166998":"0.00512229","0.02166274":"0.59849633","0.02165071":"1.00000000","0.02164315":"0.55500015","0.02161593":"0.00636546","0.02161538":"0.03441200","0.02160312":"60.58000000","0.02160100":"0.01835285","0.02160000":"6.06995926","0.02159205":"0.02623049","0.02158095":"0.00889211","0.02156660":"1.00000000","0.02155740":"0.05000000","0.02155174":"0.03314292","0.02152986":"0.05000000","0.02152751":"0.46452190","0.02152000":"4.54030457","0.02151399":"1.00000000","0.02151300":"10.00000000","0.02150838":"0.00639700","0.02150597":"0.05000000","0.02150100":"0.01813870","0.02150000":"7.40403169","0.02147939":"0.00854994","0.02147050":"0.05000000","0.02143826":"0.07209396","0.02143749":"0.05035105","0.02142283":"0.06434257","0.02140758":"0.05000000","0.02140314":"0.47656559","0.02140137":"0.00642912","0.02140100":"0.01612075","0.02140000":"6.05654206","0.02139989":"1.00000000","0.02138461":"0.03441200","0.02137470":"0.10200000","0.02136621":"0.83008660","0.02136230":"0.00708870","0.02135061":"0.21364635","0.02133295":"1.27000000","0.02132200":"1.28621424","0.02130100":"0.01278719","0.02130000":"7.05774648","0.02129489":"0.00646126","0.02129268":"0.14089395","0.02127842":"0.00901854","0.02125320":"1.00000000","0.02124505":"0.00522474","0.02123000":"0.03000000","0.02122823":"0.41447650","0.02122080":"1.24121192","0.02121000":"0.05000000","0.02120808":"1.00000000","0.02120100":"0.01282959","0.02120000":"16.38709624","0.02118500":"0.24923484","0.02117721":"0.03400000","0.02116300":"0.06000000","0.02116140":"0.05050226","0.02116091":"0.05055276","0.02115384":"0.03441200","0.02115176":"0.02836642","0.02115000":"1.47487375","0.02113953":"0.05000000","0.02112575":"0.05000000","0.02111506":"0.05000000","0.02111285":"0.05000000","0.02110803":"1.00000000","0.02110687":"0.05000000","0.02110579":"0.46269886","0.02110504":"0.05000000","0.02110100":"0.01184778","0.02110000":"6.05540427","0.02109532":"0.05000000","0.02109374":"0.05000000","0.02109287":"0.05000000","0.02107989":"0.05000000","0.02106522":"0.89500000","0.02105417":"0.10189431","0.02105237":"0.03400000","0.02105156":"1.00000000","0.02103558":"0.79650000","0.02101335":"0.09298261","0.02100100":"0.01000000","0.02100000":"19.24285681","0.02096572":"0.03400000","0.02094990":"20.00000000","0.02094415":"0.10030681","0.02093636":"0.07898980","0.02093596":"0.05000000","0.02093544":"0.05000000","0.02093209":"0.05000000","0.02092527":"0.05000000","0.02092307":"0.03441200","0.02091527":"0.05000000","0.02090100":"0.06000000","0.02090000":"8.01104498","0.02088870":"0.00879171","0.02088799":"0.00918711","0.02088502":"0.05000000","0.02086682":"0.14376939","0.02086659":"1.00000000","0.02086356":"0.03400000","0.02085000":"30.00000000","0.02084167":"0.03698696","0.02083991":"0.00532631","0.02083214":"0.05000000","0.02083179":"0.05000000","0.02083165":"0.05000000","0.02083114":"0.05000000","0.02083113":"0.05000000","0.02083085":"0.05000000","0.02083040":"0.05000000","0.02083011":"0.05000000","0.02082989":"0.05000000","0.02082615":"0.05000000","0.02082506":"0.05000000","0.02082227":"0.05000000","0.02080967":"1.00000000","0.02080100":"0.01000000","0.02080000":"32.02124327","0.02077831":"0.29116899","0.02077375":"3.21333751","0.02076769":"10.48825651","0.02075001":"0.20000000","0.02072925":"0.05000000","0.02072742":"0.05000000","0.02071796":"0.03400000","0.02071073":"0.05000000","0.02071000":"0.01000000","0.02070751":"0.05000000","0.02070339":"3.55741666","0.02070026":"0.05000000","0.02070000":"6.09865991","0.02069230":"0.03441200","0.02067440":"0.48368998","0.02063041":"0.96944269","0.02062611":"0.03400000","0.02060751":"0.19191353","0.02060172":"0.91142328","0.02060100":"0.01000000","0.02060000":"7.20258690","0.02059887":"0.05229155","0.02058800":"0.05231916","0.02052341":"0.03400000","0.02052073":"0.03400000","0.02051399":"7.29745895","0.02051135":"1.45940414","0.02051133":"0.56166156","0.02050100":"0.01085703","0.02050000":"23.57444196","0.02046876":"3.55819131","0.02046153":"0.03441200","0.02044948":"0.14670348","0.02043966":"0.15000000","0.02043446":"0.08659499","0.02043429":"0.00543204","0.02040000":"6.04927550","0.02038437":"0.00500383","0.02038100":"3.95417300","0.02036073":"0.00500964","0.02034423":"4.91539862","0.02034299":"0.57929144","0.02034000":"0.50164208","0.02033810":"2.70003590","0.02032200":"1.96831021","0.02031809":"1.58172224","0.02031062":"3.00000000","0.02031046":"1.16059163","0.02031000":"49.23682915","0.02030174":"0.49256812","0.02030100":"0.98517314","0.02030001":"1.47783179","0.02030000":"14.37874817","0.02027825":"0.10216661","0.02027417":"0.98647689","0.02025363":"0.01602951","0.02025271":"0.00942985","0.02025034":"0.40129040","0.02023467":"3.68155680","0.02023076":"0.03441200","0.02022710":"0.03400000","0.02022379":"0.00908077","0.02021100":"2.69796694","0.02021040":"5.28738818","0.02020000":"16.87018070","0.02019381":"0.17000000","0.02018980":"0.74294942","0.02018120":"1.48653202","0.02017970":"22.00000000","0.02017282":"0.05000000","0.02017117":"0.60517219","0.02010000":"18.62560448","0.02008819":"0.00103729","0.02008000":"0.50013944","0.02007506":"9.90000000","0.02007000":"80.00000000","0.02004049":"0.14969743","0.02004000":"0.00553892","0.02002070":"3.69281648","0.02001800":"0.01901900","0.02000663":"0.05005000","0.02000393":"0.03400000","0.02000133":"0.00918176","0.02000100":"10.99070146","0.02000000":"42.16328564","0.01999444":"1.00000000","0.01993256":"0.09498972","0.01991299":"0.03284640","0.01990000":"56.00552764","0.01988324":"0.17069803","0.01987417":"1.00633134","0.01986768":"0.01566111","0.01981798":"0.00926671","0.01980000":"0.02960809","0.01974055":"4.15418548","0.01973602":"6.00000000","0.01973000":"3.00000000","0.01972411":"1.01398745","0.01971660":"0.76078026","0.01970000":"0.03583757","0.01966227":"0.00934010","0.01966151":"0.09257224","0.01964860":"0.07366020","0.01963968":"0.15275248","0.01962512":"1.15769993","0.01961000":"10.00000000","0.01960000":"1.41203929","0.01959822":"0.05158173","0.01956250":"0.66453675","0.01953727":"1.15623472","0.01953685":"0.03400000","0.01952709":"0.00940475","0.01951500":"14.47357674","0.01951447":"4.21866417","0.01951092":"0.62154886","0.01951000":"9.92172681","0.01950006":"0.10200000","0.01950000":"20.97781436","0.01947503":"0.05010005","0.01947417":"1.02700141","0.01943066":"0.10426440","0.01942659":"0.05000000","0.01941899":"2.00000000","0.01940776":"0.00946258","0.01940031":"0.24258330","0.01940000":"26.50481393","0.01938455":"20.00000000","0.01937572":"0.03400000","0.01936771":"0.10290633","0.01930000":"0.01600156","0.01929370":"0.03400000","0.01928888":"1.00000000","0.01927534":"0.10200000","0.01927315":"0.10101203","0.01925450":"1.12181568","0.01924688":"0.15586993","0.01923780":"0.05000000","0.01923474":"0.05000000","0.01923421":"0.06800000","0.01922775":"0.05000000","0.01922377":"0.05000000","0.01922000":"0.03000000","0.01921807":"3.16433793","0.01920000":"1.06973231","0.01917700":"3.00000000","0.01917282":"0.05000000","0.01916979":"0.05000000","0.01916731":"0.87070000","0.01916580":"0.05000000","0.01916304":"0.64972430","0.01916200":"1.00000000","0.01916029":"0.05000000","0.01916000":"0.30793319","0.01914423":"10.44701198","0.01914000":"4.73354232","0.01911119":"0.01205210","0.01911000":"62.32862376","0.01910174":"0.52351251","0.01910100":"1.57059840","0.01910001":"2.61779968","0.01910000":"11.17831572","0.01906731":"0.87080000","0.01906000":"0.04884575","0.01905712":"0.17000000","0.01902000":"0.60000000","0.01901881":"4.34545201","0.01900000":"12.43473062","0.01899798":"0.05000000","0.01898999":"0.31595594","0.01898384":"0.10219482","0.01896731":"0.87090000","0.01896556":"0.03400000","0.01892876":"0.11452100","0.01890000":"17.63528413","0.01886731":"0.87100000","0.01886194":"0.15905097","0.01881997":"0.03400000","0.01881220":"0.00842125","0.01880400":"4.06075835","0.01880000":"1.57714947","0.01879900":"5.33486409","0.01877781":"0.07373011","0.01876731":"0.87110000","0.01875154":"3.40000000","0.01875000":"0.05000000","0.01873862":"0.03400000","0.01871348":"4.38218366","0.01870000":"0.06443102","0.01869667":"1.08423960","0.01867988":"0.03400000","0.01867052":"0.05000000","0.01866731":"0.87120000","0.01864391":"2.00000000","0.01862370":"0.03400000","0.01860000":"0.23519410","0.01857621":"0.05000000","0.01857615":"0.13600000","0.01857337":"0.05000000","0.01856731":"0.87130000","0.01856540":"0.05000000","0.01856000":"0.26939655","0.01855639":"0.05000000","0.01855545":"0.05000000","0.01854624":"0.05000000","0.01854210":"0.16179398","0.01853538":"0.05000000","0.01852058":"0.15602886","0.01851000":"4.70969584","0.01850858":"0.05000000","0.01850700":"21.00000000","0.01850230":"0.05000000","0.01850037":"12.00000000","0.01850000":"3.24427160","0.01848470":"0.16229692","0.01846731":"0.87140000","0.01845677":"0.17500000","0.01845000":"18.75474580","0.01844000":"0.20601000","0.01842686":"0.12587500","0.01840400":"10.00000000","0.01840158":"0.29955471","0.01840000":"0.70266034","0.01839994":"6.11864114","0.01838048":"2.39255369","0.01836731":"0.87150000","0.01836332":"0.17504568","0.01835928":"5.18378778","0.01834190":"0.00918361","0.01833498":"0.05380045","0.01832450":"0.00662992","0.01831100":"0.05000000","0.01830000":"0.02105410","0.01829000":"0.03000000","0.01827270":"0.00924025","0.01826731":"0.87160000","0.01823707":"0.70544227","0.01822211":"1.09756774","0.01821370":"0.00928990","0.01821100":"0.05000000","0.01820700":"5.51384632","0.01820130":"0.30500000","0.01820000":"11.01504781","0.01818180":"1.65000166","0.01818000":"0.05116282","0.01817898":"12.00000000","0.01816731":"0.87170000","0.01815918":"0.17484655","0.01814423":"22.04557593","0.01813000":"0.27578599","0.01812000":"56.36200662","0.01811500":"0.16560916","0.01811100":"0.05000000","0.01811000":"10.10000000","0.01810174":"0.55243308","0.01810156":"0.87010000","0.01810100":"2.09933153","0.01810001":"4.41988707","0.01810000":"8.79628953","0.01807173":"0.08300257","0.01806731":"0.87180000","0.01806700":"0.50000000","0.01803777":"4.76072189","0.01802824":"2385.14685849","0.01802784":"2.94337480","0.01802000":"21.00000000","0.01800761":"0.09543520","0.01800156":"0.87020000","0.01800000":"37.50460388","0.01799447":"1.82000082","0.01799000":"0.08004446","0.01796731":"0.87190000","0.01792497":"0.13845750","0.01790156":"0.87030000","0.01790000":"8.99616407","0.01788385":"3.68200000","0.01788000":"5.00000000","0.01786731":"0.87200000","0.01785719":"0.02800006","0.01785480":"0.00947380","0.01785000":"0.00577031","0.01784000":"0.06850561","0.01782206":"0.59310090","0.01780545":"0.00898601","0.01780156":"0.87040000","0.01780000":"33.11049833","0.01775270":"0.16898894","0.01775000":"0.00597184","0.01770156":"0.87050000","0.01770000":"0.01609492","0.01768900":"2.22056532","0.01768013":"0.29807869","0.01767788":"0.00848519","0.01766528":"0.16609830","0.01765601":"0.16619867","0.01765000":"0.00589236","0.01763000":"0.33285388","0.01762799":"0.00025778","0.01761252":"0.16700629","0.01760156":"0.87060000","0.01760000":"0.61586819","0.01757536":"0.16689035","0.01756318":"0.16712246","0.01755000":"0.17880571","0.01753777":"0.02000000","0.01753000":"20.00000000","0.01752940":"6.33639183","0.01752200":"0.16744844","0.01751409":"0.16746315","0.01751000":"13.70645346","0.01750705":"0.16737687","0.01750703":"0.16745370","0.01750156":"0.87070000","0.01750030":"0.16745114","0.01750001":"1.20509760","0.01750000":"4.70871739","0.01749100":"0.30000000","0.01748000":"5.72082380","0.01744199":"2.27821626","0.01742307":"0.15241720","0.01742099":"0.21000000","0.01740156":"0.87080000","0.01740000":"2.51646494","0.01739764":"0.17243775","0.01738698":"5.47367120","0.01736889":"0.01000000","0.01735751":"0.16700000","0.01735430":"0.01063611","0.01735119":"0.57632935","0.01732467":"0.87010000","0.01730156":"0.87090000","0.01730000":"0.75144510","0.01725961":"0.01912268","0.01722467":"0.87020000","0.01720156":"0.87100000","0.01718725":"0.03300000","0.01717170":"1.74706058","0.01716824":"0.15384920","0.01712467":"0.87030000","0.01711000":"0.05844536","0.01710156":"0.87110000","0.01710000":"2.76023393","0.01708000":"0.08430913","0.01707173":"0.11715275","0.01704968":"0.17595696","0.01702467":"0.87040000","0.01700333":"0.09900000","0.01700156":"0.87120000","0.01700001":"0.84698186","0.01700000":"39.04824119","0.01697110":"0.01051466","0.01695900":"0.11793149","0.01694674":"0.08487382","0.01694673":"0.04428083","0.01693337":"0.05000000","0.01693288":"0.39392944","0.01692467":"0.87050000","0.01692117":"0.16792370","0.01690420":"7.00000000","0.01690156":"0.87130000","0.01690000":"0.61952663","0.01688000":"5.00000000","0.01687541":"0.52812621","0.01686000":"2.61923132","0.01682467":"0.87060000","0.01680156":"0.87140000","0.01680000":"0.36176667","0.01672467":"0.87070000","0.01670868":"0.17954799","0.01670156":"0.87150000","0.01670000":"13.25218564","0.01662467":"0.87080000","0.01660156":"0.87160000","0.01660000":"0.10000000","0.01659400":"2.00000000","0.01658287":"0.87010000","0.01657500":"0.00604224","0.01655555":"0.31227177","0.01655000":"1.51057402","0.01654675":"0.13985949","0.01653987":"1.86424470","0.01652467":"0.87090000","0.01650156":"0.87170000","0.01650001":"0.00612121","0.01650000":"3.39627334","0.01649003":"0.69724391","0.01648287":"0.87020000","0.01647890":"0.00859464","0.01646007":"1.00000000","0.01643000":"0.12175500","0.01642467":"0.87100000","0.01641927":"0.18517070","0.01641784":"9.36286518","0.01640156":"0.87180000","0.01640000":"0.60000000","0.01639296":"0.02653151","0.01638287":"0.87030000","0.01637499":"0.30534370","0.01632968":"0.00630754","0.01632467":"0.87110000","0.01631459":"1.83884486","0.01630156":"0.87190000","0.01630000":"0.10674847","0.01628287":"0.87040000","0.01628120":"0.00874124","0.01625900":"15.37609940","0.01624594":"0.16582851","0.01622467":"0.87120000","0.01620499":"0.00647948","0.01620156":"0.87200000","0.01620000":"0.10000000","0.01618287":"0.87050000","0.01616160":"1.85625186","0.01615651":"0.55727451","0.01612467":"0.87130000","0.01612450":"0.00850627","0.01612345":"1.50000032","0.01611000":"0.06207325","0.01610000":"1.07950311","0.01608287":"0.87060000","0.01608000":"0.01243782","0.01602467":"0.87140000","0.01601000":"2.00000000","0.01600000":"69.73844821","0.01598287":"0.87070000","0.01595001":"0.03080029","0.01592467":"0.87150000","0.01591737":"0.20438010","0.01590000":"1.81005031","0.01588287":"0.87080000","0.01588000":"1.00000000","0.01587458":"0.87010000","0.01582467":"0.87160000","0.01582016":"0.98059695","0.01578287":"0.87090000","0.01577458":"0.87020000","0.01575000":"0.12700600","0.01572467":"0.87170000","0.01571705":"1.12513862","0.01570000":"1.12791530","0.01568287":"0.87100000","0.01567557":"0.03135260","0.01567458":"0.87030000","0.01562467":"0.87180000","0.01560120":"16.25228252","0.01560000":"0.20000000","0.01558287":"0.87110000","0.01557821":"0.01557821","0.01557458":"0.87040000","0.01555682":"0.17905073","0.01555555":"0.32143777","0.01552467":"0.87190000","0.01552000":"0.21477663","0.01551000":"2.00000000","0.01550000":"1.66516129","0.01548287":"0.87120000","0.01547458":"0.87050000","0.01544444":"0.32374177","0.01543000":"0.05000000","0.01542956":"6.00000000","0.01542467":"0.87200000","0.01541547":"0.22580680","0.01541469":"0.01225747","0.01538287":"0.87130000","0.01537844":"13.00616577","0.01537458":"0.87060000","0.01534000":"0.13034800","0.01533333":"0.32608777","0.01533000":"0.21743857","0.01530610":"0.01000000","0.01528287":"0.87140000","0.01527752":"1.73115860","0.01527458":"0.87070000","0.01523000":"1.03717203","0.01522222":"0.32846777","0.01520000":"263.72697170","0.01519944":"1.00000000","0.01519827":"0.87010000","0.01518434":"0.29999987","0.01518287":"0.87150000","0.01517458":"0.87080000","0.01516006":"0.05000000","0.01511111":"0.33088777","0.01510034":"0.86321566","0.01510000":"1.70000000","0.01509827":"0.87020000","0.01509000":"2.00000000","0.01508287":"0.87160000","0.01507458":"0.87090000","0.01502916":"1.08381762","0.01501000":"7.00000000","0.01500001":"0.00673333","0.01500000":"58.56291868","0.01499999":"0.33333777","0.01499827":"0.87030000","0.01498287":"0.87170000","0.01497458":"0.87100000","0.01493417":"0.03452351","0.01489827":"0.87040000","0.01488888":"0.33834777","0.01488287":"0.87180000","0.01488166":"0.05000000","0.01487458":"0.87110000","0.01482262":"0.05000000","0.01481000":"17.72435787","0.01480927":"0.10000000","0.01479827":"0.87050000","0.01478424":"0.03381980","0.01478287":"0.87190000","0.01477777":"0.33834777","0.01477458":"0.87120000","0.01472112":"0.05000000","0.01469827":"0.87060000","0.01468287":"0.87200000","0.01467458":"0.87130000","0.01466666":"0.34091777","0.01462006":"0.05000000","0.01459930":"1.95654792","0.01459827":"0.87070000","0.01457458":"0.87140000","0.01455555":"0.34351777","0.01455250":"0.87010000","0.01452668":"0.03333300","0.01452068":"0.03333300","0.01451200":"68.90848953","0.01450001":"0.05000000","0.01450000":"0.82500000","0.01449827":"0.87080000","0.01447458":"0.87150000","0.01445250":"0.87020000","0.01444444":"0.37293934","0.01441945":"0.05000000","0.01439827":"0.87090000","0.01437458":"0.87160000","0.01435250":"0.87030000","0.01431000":"0.13972000","0.01429827":"0.87100000","0.01427770":"1.19790356","0.01427458":"0.87170000","0.01425250":"0.87040000","0.01423759":"0.30000000","0.01422222":"0.38468537","0.01420000":"0.05000000","0.01419827":"0.87110000","0.01417458":"0.87180000","0.01415250":"0.87050000","0.01409827":"0.87120000","0.01407458":"0.87190000","0.01405902":"0.00711999","0.01405250":"0.87060000","0.01400641":"0.05000000","0.01400000":"53.05114286","0.01399999":"0.39405242","0.01399827":"0.87130000","0.01397458":"0.87200000","0.01395250":"0.87070000","0.01395000":"0.14339700","0.01394554":"0.00788783","0.01389827":"0.87140000","0.01385250":"0.87080000","0.01382084":"0.10000000","0.01379827":"0.87150000","0.01378040":"0.10000000","0.01377777":"0.41996779","0.01375250":"0.87090000","0.01370007":"13.00000000","0.01369827":"0.87160000","0.01366666":"0.36548777","0.01366600":"1.50000000","0.01365250":"0.87100000","0.01359827":"0.87170000","0.01355555":"0.36848777","0.01355250":"0.87110000","0.01350001":"0.04060737","0.01349827":"0.87180000","0.01349000":"0.24709661","0.01345250":"0.87120000","0.01339827":"0.87190000","0.01335250":"0.87130000","0.01333333":"0.38644955","0.01329827":"0.87200000","0.01328424":"1.05388039","0.01325250":"0.87140000","0.01325069":"0.10000000","0.01323759":"0.30000000","0.01323188":"0.05000000","0.01322222":"0.37777213","0.01315562":"3.80065710","0.01315250":"0.87150000","0.01305250":"0.87160000","0.01303000":"0.23400000","0.01300000":"50.93724077","0.01299999":"0.43083695","0.01296794":"0.10000000","0.01295250":"0.87170000","0.01288888":"0.38754777","0.01286007":"0.05000000","0.01285250":"0.87180000","0.01277777":"0.39091220","0.01277766":"0.01277766","0.01275250":"0.87190000","0.01270000":"2.50000000","0.01266666":"0.21710528","0.01265250":"0.87200000","0.01264009":"0.03333300","0.01260000":"0.80000000","0.01259000":"6.95316686","0.01255555":"0.40400221","0.01254926":"0.16697325","0.01251212":"0.49999997","0.01250000":"0.88000000","0.01244444":"0.40413777","0.01239142":"0.10000000","0.01234567":"0.76430224","0.01233333":"1.71320564","0.01230000":"25.56692520","0.01228705":"0.01561809","0.01223759":"0.93539006","0.01222222":"0.42222996","0.01215114":"0.15185528","0.01215112":"0.28745677","0.01215110":"1.52650418","0.01211111":"0.42449777","0.01206788":"0.05000000","0.01201989":"0.05000000","0.01200000":"53.38662694","0.01199999":"0.43026777","0.01190000":"2.50000000","0.01188888":"0.42322777","0.01180011":"6.37080634","0.01177777":"0.43477577","0.01172008":"0.15000000","0.01172006":"0.05000000","0.01168471":"0.03333300","0.01168089":"0.10000000","0.01167305":"0.10000000","0.01166666":"0.43657577","0.01164886":"0.05000000","0.01164000":"0.05000000","0.01162499":"0.08284588","0.01160000":"2.17241466","0.01158489":"0.03333300","0.01156086":"0.03333300","0.01156067":"0.10000000","0.01155555":"0.47279977","0.01152000":"2.50000000","0.01144444":"0.44664777","0.01133333":"0.45762797","0.01130602":"0.05000000","0.01124698":"1.00000000","0.01122222":"0.46234777","0.01122000":"1.78253120","0.01111111":"0.46716777","0.01104554":"0.00995878","0.01100000":"7.07893074","0.01099999":"0.95083037","0.01089000":"0.30609122","0.01077777":"0.46392777","0.01072406":"0.10000000","0.01072000":"5.00000000","0.01066666":"0.46875777","0.01065500":"0.31284217","0.01055555":"0.47368777","0.01044444":"0.47872777","0.01040151":"6.02529465","0.01035000":"96.61835749","0.01034667":"0.32216495","0.01033333":"0.48387177","0.01033000":"2.10000000","0.01032398":"2.84523120","0.01029405":"0.10000000","0.01026000":"0.26500000","0.01022222":"1.00000000","0.01022000":"0.32615786","0.01012375":"1.00000000","0.01011111":"0.49450777","0.01006118":"0.10000000","0.01002967":"0.18002967","0.01000778":"9.47280346","0.01000679":"0.10000000","0.01000001":"0.01099999","0.01000000":"57.22867792","0.00999999":"0.50000777","0.00977777":"0.51136777","0.00955555":"0.52325777","0.00950653":"0.34612572","0.00940000":"0.11740363","0.00935965":"0.10000000","0.00919000":"0.36271309","0.00911111":"1.00000000","0.00904534":"0.01216096","0.00900000":"6.66746222","0.00899999":"0.55555777","0.00899333":"0.37064492","0.00896061":"0.10000000","0.00896000":"0.37202381","0.00895590":"0.02050574","0.00895383":"5.58420252","0.00880000":"0.10000000","0.00877777":"0.56962777","0.00860000":"7.80000000","0.00855999":"199.99919929","0.00842000":"2.50000000","0.00833333":"1.93200078","0.00830397":"0.10392986","0.00811111":"1.00000000","0.00811000":"1.50000000","0.00808000":"2.77624753","0.00800121":"0.62490548","0.00800000":"254.62500124","0.00799999":"0.62500777","0.00777000":"1.00000000","0.00776000":"0.42955326","0.00770000":"1.29870130","0.00766500":"0.43487715","0.00757568":"1.00000000","0.00755555":"0.66176777","0.00755005":"0.09433712","0.00750000":"10.00000000","0.00747111":"8.38860124","0.00744094":"0.09312933","0.00735028":"482.32137279","0.00730000":"0.20225479","0.00726000":"0.45913682","0.00724000":"0.08813430","0.00723000":"0.64000002","0.00722222":"0.69231777","0.00711111":"1.00000000","0.00710333":"0.46926326","0.00704554":"0.01561272","0.00701111":"1.00000000","0.00690000":"23.00000000","0.00674798":"0.90687198","0.00674500":"0.49419323","0.00638390":"0.09666600","0.00625000":"1.76000000","0.00621609":"0.17306286","0.00620000":"20.00000000","0.00612667":"0.54406964","0.00611111":"1.00000000","0.00609034":"0.88303280","0.00601111":"1.00000000","0.00600000":"0.20678446","0.00597333":"0.55803571","0.00580000":"0.11562725","0.00567337":"0.17626208","0.00564222":"0.05176866","0.00555555":"2.00000000","0.00547603":"1.00000000","0.00544500":"0.61218243","0.00539000":"1.00000000","0.00532750":"0.62568434","0.00517941":"0.10000000","0.00517333":"0.64432990","0.00514683":"0.06397259","0.00514534":"0.02137857","0.00511280":"18.54203822","0.00511000":"0.65231572","0.00501111":"2.00000000","0.00500100":"1.10000000","0.00500000":"0.60545120","0.00480000":"5.00000000","0.00459500":"0.72542619","0.00450000":"2.04440667","0.00449667":"0.74128984","0.00448000":"0.74404762","0.00444444":"3.00000000","0.00420000":"15.00000000","0.00401111":"2.00000000","0.00401000":"3.00000000","0.00400121":"0.50201813","0.00388000":"0.85910653","0.00383250":"0.86975429","0.00364200":"51.24272652","0.00363000":"0.91827365","0.00360408":"0.90000000","0.00356765":"0.09000000","0.00355167":"0.93852651","0.00351100":"6.19640231","0.00347837":"12.93709410","0.00347508":"0.10000000","0.00337250":"0.98838646","0.00333624":"1.00000000","0.00333333":"5.91332718","0.00320000":"3.12500000","0.00319327":"0.07254321","0.00306333":"1.08813928","0.00301111":"2.00000000","0.00301000":"3.00000000","0.00300126":"0.66638678","0.00300000":"3.90000000","0.00298667":"1.11607143","0.00282781":"1.00000000","0.00281180":"0.03559998","0.00276383":"0.99000000","0.00272250":"1.22436486","0.00271133":"0.04635562","0.00270000":"1.00000000","0.00267500":"1.00000000","0.00267120":"374.36358192","0.00266375":"1.25136868","0.00259554":"0.19264199","0.00251436":"0.07671579","0.00251285":"1.00000000","0.00250000":"0.04455052","0.00233333":"2.14286777","0.00229750":"1.45085238","0.00224672":"1.00000008","0.00224000":"1.48809524","0.00222222":"5.00000000","0.00220271":"18.66289707","0.00220000":"0.10000000","0.00217300":"0.06250000","0.00201116":"2.48612740","0.00201111":"6.97237843","0.00200100":"15.00000000","0.00200000":"54.78000000","0.00190428":"0.99000000","0.00186231":"1.00000000","0.00180000":"1.00000000","0.00175996":"0.14457147","0.00160000":"6.25000000","0.00156666":"3.23396270","0.00150001":"133.06577956","0.00150000":"1.13333334","0.00148993":"10.00000000","0.00139070":"0.24041795","0.00138451":"1.00000000","0.00138000":"0.45000000","0.00137002":"4.00382284","0.00133333":"0.30000000","0.00131136":"1.00000000","0.00130842":"1.00000000","0.00129777":"0.38528398","0.00124333":"0.10000000","0.00123333":"0.09000000","0.00122333":"0.08901089","0.00118304":"82.03793208","0.00112233":"10.00000000","0.00111000":"21.63841180","0.00110000":"1.00000000","0.00102000":"1.00000000","0.00101111":"10.00000000","0.00100110":"150.00000000","0.00100100":"10.00000000","0.00100000":"181.20000000","0.00090111":"5.00000000","0.00087300":"12.00000000","0.00084828":"1.00000000","0.00080111":"5.00000000","0.00080000":"12.50000000","0.00079301":"10.00000000","0.00077999":"1.00000000","0.00073726":"1.00000000","0.00070111":"5.00000000","0.00070000":"1.00000000","0.00064889":"0.77056203","0.00060111":"5.00000000","0.00060000":"4.16837134","0.00052451":"1.00000000","0.00050130":"3.34127269","0.00050111":"5.00000000","0.00050000":"3.00000000","0.00046193":"2164.78705892","0.00045663":"1.00000000","0.00043148":"1.94319078","0.00042000":"10.00000000","0.00040111":"5.00000000","0.00040100":"8.60995012","0.00040000":"27.50016378","0.00036041":"0.90000000","0.00033235":"100.00000000","0.00033234":"451.33550174","0.00032472":"1.00000000","0.00032444":"1.54111700","0.00032266":"6.19850617","0.00030111":"5.00000000","0.00030000":"5.00000000","0.00029763":"1.00000000","0.00024000":"1.00000000","0.00023500":"1.00306383","0.00020618":"150.00000000","0.00020111":"5.00000000","0.00020010":"40.00000000","0.00020000":"1055.00000000","0.00017000":"1.00000000","0.00016222":"3.08223400","0.00015883":"100.00000000","0.00015882":"1259.28724342","0.00015054":"1.00000000","0.00013334":"1.00000000","0.00011540":"1.00000000","0.00011164":"1.00000000","0.00011111":"89.09189092","0.00010650":"9.00000000","0.00010510":"2.00000000","0.00010359":"1.00000000","0.00010111":"10.00000000","0.00010000":"2052.10260000","0.00009726":"17.85554185","0.00009170":"10.00000000","0.00008800":"8.00000000","0.00008000":"2.02050000","0.00007186":"6.95811300","0.00006060":"130.00000000","0.00005126":"1070.00000000","0.00005120":"195.31250000","0.00005000":"2120.00000000","0.00004295":"202.34435389","0.00004168":"95.96928983","0.00004000":"200.00000000","0.00003638":"137.43815283","0.00003500":"114.28657143","0.00003492":"6.90074951","0.00003101":"500.00000000","0.00003100":"1000.00000000","0.00002560":"390.62500000","0.00002500":"20000.00000000","0.00002000":"55.00000000","0.00001280":"781.25000000","0.00001010":"50.00000000","0.00001005":"146.26965174","0.00001000":"12109.99999999","0.00000640":"1562.50000000","0.00000550":"800.00000000","0.00000500":"200.00000000","0.00000331":"1000.00000000","0.00000330":"11479.02727273","0.00000320":"3125.00000000","0.00000200":"1000.00000001","0.00000178":"65.00000000","0.00000170":"100.00000000","0.00000164":"210.17073171","0.00000160":"6250.00000000","0.00000100":"1999.00000000","0.00000095":"1612.31578947","0.00000090":"1111.11111111","0.00000080":"12500.00000000","0.00000054":"557.96296296","0.00000040":"25000.00000000","0.00000020":"50000.00000000","0.00000010":"200000.00000000","0.00000005":"200000.00000000","0.00000004":"2500.00000000","0.00000002":"556100.00000000","0.00000001":"1182263.00000000"}]}]]]`) + pressXToJSON := []byte(`[148,827987828,[["i",{"currencyPair":"BTC_ETH","orderBook":[{"0.02311264":"2.20557811","1000.02022945":"1.00000000","1000.17618025":"0.00100000","1148.00000000":"0.04594689","1997.00000000":"2.00000000","2000.00000000":"0.00000206","3000.00000000":"0.00000137","3772.00000000":"0.65977073","4000.00000000":"0.00000103","5000.00000000":"0.10284089"},{"0.02310611":"21.20361406","0.00010000":"2052.10260000","0.00009726":"17.85554185","0.00009170":"10.00000000","0.00008800":"8.00000000","0.00008000":"2.02050000","0.00007186":"6.95811300","0.00006060":"130.00000000","0.00005126":"1070.00000000","0.00005120":"195.31250000","0.00005000":"2120.00000000","0.00004295":"202.34435389","0.00004168":"95.96928983","0.00004000":"200.00000000","0.00003638":"137.43815283","0.00003500":"114.28657143","0.00003492":"6.90074951","0.00003101":"500.00000000","0.00003100":"1000.00000000","0.00002560":"390.62500000","0.00002500":"20000.00000000","0.00002000":"55.00000000","0.00001280":"781.25000000","0.00001010":"50.00000000","0.00001005":"146.26965174","0.00001000":"12109.99999999","0.00000640":"1562.50000000","0.00000550":"800.00000000","0.00000500":"200.00000000","0.00000331":"1000.00000000","0.00000330":"11479.02727273","0.00000320":"3125.00000000","0.00000200":"1000.00000001","0.00000178":"65.00000000","0.00000170":"100.00000000","0.00000164":"210.17073171","0.00000160":"6250.00000000","0.00000100":"1999.00000000","0.00000095":"1612.31578947","0.00000090":"1111.11111111","0.00000080":"12500.00000000","0.00000054":"557.96296296","0.00000040":"25000.00000000","0.00000020":"50000.00000000","0.00000010":"200000.00000000","0.00000005":"200000.00000000","0.00000004":"2500.00000000","0.00000002":"556100.00000000","0.00000001":"1182263.00000000"}]}]]]`) err = p.wsHandleData(pressXToJSON) if err != nil { t.Error(err) @@ -572,3 +572,36 @@ func TestGetHistoricCandlesExtended(t *testing.T) { t.Fatal(err) } } + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_XMR") + if err != nil { + t.Fatal(err) + } + if mockTests { + t.Skip("relies on time.Now()") + } + _, err = p.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("BTC_XMR") + if err != nil { + t.Fatal(err) + } + tStart := time.Date(2020, 6, 6, 0, 0, 0, 0, time.UTC) + tEnd := time.Date(2020, 6, 6, 1, 0, 0, 0, time.UTC) + if !mockTests { + tStart = time.Date(2020, time.Now().Month()-3, 6, 0, 0, 0, 0, time.UTC) + tEnd = time.Date(2020, time.Now().Month()-3, 7, 0, 0, 0, 0, time.UTC) + } + _, err = p.GetHistoricTrades(currencyPair, asset.Spot, tStart, tEnd) + if err != nil { + t.Error(err) + } +} diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 0d1c2b04..16507609 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" ) const ( @@ -311,9 +312,12 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { return err } case "t": + if !p.IsSaveTradeDataEnabled() { + return nil + } currencyPair := currencyIDMap[channelID] - var trade WsTrade - trade.Symbol = currencyIDMap[channelID] + var t WsTrade + t.Symbol = currencyIDMap[channelID] dataL3, ok := dataL2.([]interface{}) if !ok { return errors.New("websocket trade update error: type conversion failure") @@ -324,14 +328,14 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { } // tradeID type intermittently changes - switch t := dataL3[1].(type) { + switch tradeIDData := dataL3[1].(type) { case string: - trade.TradeID, err = strconv.ParseInt(t, 10, 64) + t.TradeID, err = strconv.ParseInt(tradeIDData, 10, 64) if err != nil { return err } case float64: - trade.TradeID = int64(t) + t.TradeID = int64(tradeIDData) default: return fmt.Errorf("unhandled type for websocket trade update: %v", t) } @@ -340,28 +344,31 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error { if dataL3[2].(float64) != 1 { side = order.Sell } - trade.Volume, err = strconv.ParseFloat(dataL3[3].(string), 64) + t.Volume, err = strconv.ParseFloat(dataL3[3].(string), 64) if err != nil { return err } - trade.Price, err = strconv.ParseFloat(dataL3[4].(string), 64) + t.Price, err = strconv.ParseFloat(dataL3[4].(string), 64) if err != nil { return err } - trade.Timestamp = int64(dataL3[5].(float64)) + t.Timestamp = int64(dataL3[5].(float64)) pair, err := currency.NewPairFromString(currencyPair) if err != nil { return err } - p.Websocket.DataHandler <- stream.TradeData{ - Timestamp: time.Unix(trade.Timestamp, 0), + return p.AddTradesToBuffer(trade.Data{ + TID: strconv.FormatInt(t.TradeID, 10), + Exchange: p.Name, CurrencyPair: pair, + AssetType: asset.Spot, Side: side, - Amount: trade.Volume, - Price: trade.Price, - } + Price: t.Price, + Amount: t.Volume, + Timestamp: time.Unix(t.Timestamp, 0), + }) default: p.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: p.Name + stream.UnhandledMessage + string(respRaw)} return nil diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index 054cf4e0..b70e407a 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -2,6 +2,7 @@ package poloniex import ( "fmt" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -408,9 +410,76 @@ func (p *Poloniex) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (p *Poloniex) GetExchangeHistory(currencyPair currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (p *Poloniex) GetRecentTrades(currencyPair currency.Pair, assetType asset.Item) ([]trade.Data, error) { + return p.GetHistoricTrades(currencyPair, assetType, time.Now().Add(-time.Minute*15), time.Now()) +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (p *Poloniex) GetHistoricTrades(currencyPair currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { + if timestampEnd.After(time.Now()) || timestampEnd.Before(timestampStart) { + return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v", timestampStart, timestampEnd) + } + var err error + currencyPair, err = p.FormatExchangeCurrency(currencyPair, assetType) + if err != nil { + return nil, err + } + + var resp []trade.Data + ts := timestampStart +allTrades: + for { + var tradeData []TradeHistory + tradeData, err = p.GetTradeHistory(currencyPair.String(), ts.Unix(), timestampEnd.Unix()) + if err != nil { + return nil, err + } + for i := range tradeData { + var tt time.Time + tt, err = time.Parse(common.SimpleTimeFormat, tradeData[i].Date) + if err != nil { + return nil, err + } + if (tt.Before(timestampStart) && !timestampStart.IsZero()) || (tt.After(timestampEnd) && !timestampEnd.IsZero()) { + break allTrades + } + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Type) + if err != nil { + return nil, err + } + resp = append(resp, trade.Data{ + Exchange: p.Name, + TID: strconv.FormatInt(tradeData[i].TradeID, 10), + CurrencyPair: currencyPair, + AssetType: assetType, + Side: side, + Price: tradeData[i].Rate, + Amount: tradeData[i].Amount, + Timestamp: tt, + }) + if i == len(tradeData)-1 { + if ts.Equal(tt) { + // reached end of trades to crawl + break allTrades + } + if timestampStart.IsZero() { + break allTrades + } + ts = tt + } + } + } + + err = p.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + resp = trade.FilterTradesByTime(resp, timestampStart, timestampEnd) + + sort.Sort(trade.ByDate(resp)) + return resp, nil } // SubmitOrder submits a new order diff --git a/exchanges/stream/stream_types.go b/exchanges/stream/stream_types.go index 311d26a6..76006234 100644 --- a/exchanges/stream/stream_types.go +++ b/exchanges/stream/stream_types.go @@ -57,18 +57,6 @@ type PingHandler struct { Delay time.Duration } -// TradeData defines trade data -type TradeData struct { - Timestamp time.Time - CurrencyPair currency.Pair - AssetType asset.Item - Exchange string - EventType order.Type - Price float64 - Amount float64 - Side order.Side -} - // FundingData defines funding data type FundingData struct { Timestamp time.Time diff --git a/exchanges/trade/README.md b/exchanges/trade/README.md new file mode 100644 index 00000000..cbfa492b --- /dev/null +++ b/exchanges/trade/README.md @@ -0,0 +1,112 @@ +# GoCryptoTrader package Trade + + + + +[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader) +[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE) +[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/trade) +[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader) + + +This trade package is part of the GoCryptoTrader codebase. + +## This is still in active development + +You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader). + +Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk) + +## Current Features for trade + ++ The trade package contains a processor for both REST and websocket trade history processing + + Its primary purpose is to collect trade data from multiple sources and save it to the database's trade table + + If you do not have database enabled, then trades will not be processed + +### Requirements to save a trade to the database ++ Database has to be enabled ++ Under `config.json`, under your selected exchange, enable the field `saveTradeData` + + This will enable trade processing to occur for that specific exchange + + This can also be done via gRPC under the `SetExchangeTradeProcessing` command + +### Usage ++ To send trade data to be processed, use the following example: +``` +err := trade.AddTradesToBuffer(b.Name, trade.Data{ + Exchange: b.Name, + TID: strconv.FormatInt(tradeData[i].TID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTS, +}) +``` +_b in this context is an `IBotExchange` implemented struct_ + +### Rules ++ If the trade processor has not started, it will automatically start upon being sent trade data. ++ The processor will add all received trades to a buffer ++ After 15 seconds, the trade processor will parse and save all trades on the buffer to the trade table + + This is to save on constant writing to the database. Trade data, especially when received via websocket would cause massive issues on the round trip of saving data for every trade ++ If the processor has not received any trades in that 15 second timeframe, it will shut down. + + Sending trade data to it later will automatically start it up again + + +## Exchange Support Table + +| Exchange | Recent Trades via REST | Live trade updates via Websocket | Trade history via REST | +|----------|------|-----------|-----| +| Alphapoint | No | No | No | +| Binance| Yes | Yes | No | +| Bitfinex | Yes | Yes | Yes | +| Bitflyer | Yes | No | No | +| Bithumb | Yes | NA | No | +| BitMEX | Yes | Yes | Yes | +| Bitstamp | Yes | Yes | No | +| Bittrex | Yes | No | No | +| BTCMarkets | Yes | Yes | No | +| BTSE | Yes | Yes | No | +| Coinbene | Yes | Yes | No | +| CoinbasePro | Yes | Yes | No| +| COINUT | Yes | Yes | No | +| Exmo | Yes | NA | No | +| FTX | Yes | Yes | Yes | +| GateIO | Yes | Yes | No | +| Gemini | Yes | Yes | Yes | +| HitBTC | Yes | Yes | Yes | +| Huobi.Pro | Yes | Yes | No | +| ItBit | Yes | NA | No | +| Kraken | Yes | Yes | No | +| LakeBTC | Yes | No | No | +| Lbank | Yes | No | Yes | +| LocalBitcoins | Yes | NA | No | +| OKCoin International | Yes | Yes | No | +| OKEX | Yes | Yes | No | +| Poloniex | Yes | Yes | Yes | +| Yobit | Yes | NA | No | +| ZB.COM | Yes | Yes | No | + + +### Please click GoDocs chevron above to view current GoDoc information for this package + +## Contribution + +Please feel free to submit any pull requests or suggest any desired features to be added. + +When submitting a PR, please abide by our coding guidelines: + ++ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). ++ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. ++ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md). ++ Pull requests need to be based on and opened against the `master` branch. + +## Donations + + + +If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to: + +***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc*** diff --git a/exchanges/trade/trade.go b/exchanges/trade/trade.go new file mode 100644 index 00000000..51cd5abd --- /dev/null +++ b/exchanges/trade/trade.go @@ -0,0 +1,271 @@ +package trade + +import ( + "errors" + "fmt" + "sort" + "sync" + "sync/atomic" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/database" + tradesql "github.com/thrasher-corp/gocryptotrader/database/repository/trade" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/log" +) + +// Setup creates the trade processor if trading is supported +func (p *Processor) setup(wg *sync.WaitGroup) { + p.mutex.Lock() + p.bufferProcessorInterval = BufferProcessorIntervalTime + p.mutex.Unlock() + go p.Run(wg) +} + +// AddTradesToBuffer will push trade data onto the buffer +func AddTradesToBuffer(exchangeName string, data ...Data) error { + if database.DB == nil || database.DB.Config == nil || !database.DB.Config.Enabled { + return nil + } + if len(data) == 0 { + return nil + } + var errs common.Errors + if atomic.AddInt32(&processor.started, 0) == 0 { + var wg sync.WaitGroup + wg.Add(1) + processor.setup(&wg) + wg.Wait() + } + var validDatas []Data + for i := range data { + if data[i].Price == 0 || + data[i].Amount == 0 || + data[i].CurrencyPair.IsEmpty() || + data[i].Exchange == "" || + data[i].Timestamp.IsZero() { + errs = append(errs, fmt.Errorf("%v received invalid trade data: %+v", exchangeName, data[i])) + continue + } + + if data[i].Price < 0 { + data[i].Price *= -1 + data[i].Side = order.Sell + } + if data[i].Amount < 0 { + data[i].Amount *= -1 + data[i].Side = order.Sell + } + if data[i].Side == order.Bid { + data[i].Side = order.Buy + } + if data[i].Side == order.Ask { + data[i].Side = order.Sell + } + uu, err := uuid.NewV4() + if err != nil { + errs = append(errs, fmt.Errorf("%s uuid failed to generate for trade: %+v", exchangeName, data[i])) + } + data[i].ID = uu + validDatas = append(validDatas, data[i]) + } + processor.mutex.Lock() + processor.buffer = append(processor.buffer, validDatas...) + processor.mutex.Unlock() + if len(errs) > 0 { + return errs + } + return nil +} + +// Processor will save trade data to the database in batches +func (p *Processor) Run(wg *sync.WaitGroup) { + wg.Done() + if !atomic.CompareAndSwapInt32(&p.started, 0, 1) { + log.Error(log.Trade, "trade processor already started") + return + } + defer func() { + atomic.CompareAndSwapInt32(&p.started, 1, 0) + }() + p.mutex.Lock() + ticker := time.NewTicker(p.bufferProcessorInterval) + p.mutex.Unlock() + for { + <-ticker.C + p.mutex.Lock() + bufferCopy := append(p.buffer[:0:0], p.buffer...) + p.buffer = nil + p.mutex.Unlock() + if len(bufferCopy) == 0 { + ticker.Stop() + return + } + err := SaveTradesToDatabase(bufferCopy...) + if err != nil { + log.Error(log.Trade, err) + } + } +} + +// SaveTradesToDatabase converts trades and saves results to database +func SaveTradesToDatabase(trades ...Data) error { + sqlTrades, err := tradeToSQLData(trades...) + if err != nil { + return err + } + err = tradesql.Insert(sqlTrades...) + if err != nil { + return err + } + return nil +} + +// GetTradesInRange calls db function to return trades in range +// to minimise tradesql package usage +func GetTradesInRange(exchangeName, assetType, base, quote string, startDate, endDate time.Time) ([]Data, error) { + if exchangeName == "" || assetType == "" || base == "" || quote == "" || startDate.IsZero() || endDate.IsZero() { + return nil, errors.New("invalid arguments received") + } + results, err := tradesql.GetInRange(exchangeName, assetType, base, quote, startDate, endDate) + if err != nil { + return nil, err + } + return SQLDataToTrade(results...) +} + +func tradeToSQLData(trades ...Data) ([]tradesql.Data, error) { + sort.Sort(ByDate(trades)) + var results []tradesql.Data + for i := range trades { + tradeID, err := uuid.NewV4() + if err != nil { + return nil, err + } + results = append(results, tradesql.Data{ + ID: tradeID.String(), + Timestamp: trades[i].Timestamp, + Exchange: trades[i].Exchange, + Base: trades[i].CurrencyPair.Base.String(), + Quote: trades[i].CurrencyPair.Quote.String(), + AssetType: trades[i].AssetType.String(), + Price: trades[i].Price, + Amount: trades[i].Amount, + Side: trades[i].Side.String(), + TID: trades[i].TID, + }) + } + return results, nil +} + +// SQLDataToTrade converts sql data to glorious trade data +func SQLDataToTrade(dbTrades ...tradesql.Data) (result []Data, err error) { + for i := range dbTrades { + var cp currency.Pair + cp, err = currency.NewPairFromStrings(dbTrades[i].Base, dbTrades[i].Quote) + if err != nil { + return nil, err + } + cp = cp.Upper() + var a = asset.Item(dbTrades[i].AssetType) + if !a.IsValid() { + return nil, fmt.Errorf("invalid asset type %v", a) + } + var s order.Side + s, err = order.StringToOrderSide(dbTrades[i].Side) + if err != nil { + return nil, err + } + result = append(result, Data{ + ID: uuid.FromStringOrNil(dbTrades[i].ID), + Timestamp: dbTrades[i].Timestamp.UTC(), + Exchange: dbTrades[i].Exchange, + CurrencyPair: cp.Upper(), + AssetType: a, + Price: dbTrades[i].Price, + Amount: dbTrades[i].Amount, + Side: s, + }) + } + return result, nil +} + +// ConvertTradesToCandles turns trade data into kline.Items +func ConvertTradesToCandles(interval kline.Interval, trades ...Data) (kline.Item, error) { + if len(trades) == 0 { + return kline.Item{}, errors.New("no trades supplied") + } + groupedData := groupTradesToInterval(interval, trades...) + candles := kline.Item{ + Exchange: trades[0].Exchange, + Pair: trades[0].CurrencyPair, + Asset: trades[0].AssetType, + Interval: interval, + } + for k, v := range groupedData { + candles.Candles = append(candles.Candles, classifyOHLCV(time.Unix(k, 0), v...)) + } + + return candles, nil +} + +func groupTradesToInterval(interval kline.Interval, times ...Data) map[int64][]Data { + groupedData := make(map[int64][]Data) + for i := range times { + nearestInterval := getNearestInterval(times[i].Timestamp, interval) + groupedData[nearestInterval] = append( + groupedData[nearestInterval], + times[i], + ) + } + return groupedData +} + +func getNearestInterval(t time.Time, interval kline.Interval) int64 { + return t.Truncate(interval.Duration()).UTC().Unix() +} + +func classifyOHLCV(t time.Time, datas ...Data) (c kline.Candle) { + sort.Sort(ByDate(datas)) + c.Open = datas[0].Price + c.Close = datas[len(datas)-1].Price + for i := range datas { + if datas[i].Price < 0 { + datas[i].Price *= -1 + } + if datas[i].Amount < 0 { + datas[i].Amount *= -1 + } + if datas[i].Price < c.Low || c.Low == 0 { + c.Low = datas[i].Price + } + if datas[i].Price > c.High { + c.High = datas[i].Price + } + c.Volume += datas[i].Amount + } + c.Time = t + return c +} + +// FilterTradesByTime removes any trades that are not between the start +// and end times +func FilterTradesByTime(trades []Data, startTime, endTime time.Time) []Data { + if startTime.IsZero() || endTime.IsZero() { + // can't filter without boundaries + return trades + } + var filteredTrades []Data + for i := range trades { + if trades[i].Timestamp.After(startTime) && trades[i].Timestamp.Before(endTime) { + filteredTrades = append(filteredTrades, trades[i]) + } + } + + return filteredTrades +} diff --git a/exchanges/trade/trade_test.go b/exchanges/trade/trade_test.go new file mode 100644 index 00000000..2db63a09 --- /dev/null +++ b/exchanges/trade/trade_test.go @@ -0,0 +1,251 @@ +package trade + +import ( + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/database" + "github.com/thrasher-corp/gocryptotrader/database/drivers" + sqltrade "github.com/thrasher-corp/gocryptotrader/database/repository/trade" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" +) + +func TestAddTradesToBuffer(t *testing.T) { + t.Parallel() + processor.mutex.Lock() + processor.bufferProcessorInterval = BufferProcessorIntervalTime + processor.mutex.Unlock() + dbConf := database.Config{ + Enabled: true, + Driver: database.DBSQLite3, + ConnectionDetails: drivers.ConnectionDetails{ + Host: "localhost", + Database: "./rpctestdb", + }, + } + var wg sync.WaitGroup + wg.Add(1) + processor.setup(&wg) + wg.Wait() + database.DB.Config = &dbConf + cp, _ := currency.NewPairFromString("BTC-USD") + err := AddTradesToBuffer("test!", []Data{ + { + Timestamp: time.Now(), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + }, + }...) + if err != nil { + t.Error(err) + } + if atomic.AddInt32(&processor.started, 0) == 0 { + t.Error("expected the processor to have started") + } + + err = AddTradesToBuffer("test!", []Data{ + { + Timestamp: time.Now(), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 0, + Amount: 0, + Side: order.Buy, + }, + }...) + if err == nil { + t.Error("expected error") + } + processor.mutex.Lock() + processor.buffer = nil + processor.mutex.Unlock() + + err = AddTradesToBuffer("test!", []Data{ + { + Timestamp: time.Now(), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: -1, + Amount: -1, + Side: "", + }, + }...) + if err != nil { + t.Error(err) + } + processor.mutex.Lock() + if processor.buffer[0].Amount != 1 { + t.Error("expected positive amount") + } + if processor.buffer[0].Side != order.Sell { + t.Error("expected unknown side") + } + processor.mutex.Unlock() +} + +func TestSqlDataToTrade(t *testing.T) { + t.Parallel() + uuiderino, _ := uuid.NewV4() + data, err := SQLDataToTrade(sqltrade.Data{ + ID: uuiderino.String(), + Timestamp: time.Time{}, + Exchange: "hello", + Base: currency.BTC.String(), + Quote: currency.USD.String(), + AssetType: "spot", + Price: 1337, + Amount: 1337, + Side: "buy", + }) + if err != nil { + t.Error(err) + } + if len(data) != 1 { + t.Fatal("unexpected scenario") + } + if data[0].Side != order.Buy { + t.Error("expected buy side") + } + if data[0].CurrencyPair.String() != "BTCUSD" { + t.Errorf("expected \"BTCUSD\", got %v", data[0].CurrencyPair) + } + if data[0].AssetType != asset.Spot { + t.Error("expected spot") + } +} + +func TestTradeToSQLData(t *testing.T) { + t.Parallel() + cp := currency.NewPair(currency.BTC, currency.USD) + sqlData, err := tradeToSQLData(Data{ + Timestamp: time.Now(), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + }) + if err != nil { + t.Error(err) + } + if len(sqlData) != 1 { + t.Fatal("unexpected result") + } + if sqlData[0].Base != cp.Base.String() { + t.Errorf("expected \"BTC\", got %v", sqlData[0].Base) + } + if sqlData[0].AssetType != asset.Spot.String() { + t.Error("expected spot") + } +} + +func TestConvertTradesToCandles(t *testing.T) { + t.Parallel() + cp, _ := currency.NewPairFromString("BTC-USD") + startDate := time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC) + candles, err := ConvertTradesToCandles(kline.FifteenSecond, []Data{ + { + Timestamp: startDate, + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + }, + { + Timestamp: startDate.Add(time.Second), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: 1337, + Amount: 1337, + Side: order.Buy, + }, + { + Timestamp: startDate.Add(time.Minute), + Exchange: "test!", + CurrencyPair: cp, + AssetType: asset.Spot, + Price: -1337, + Amount: -1337, + Side: order.Buy, + }, + }...) + if err != nil { + t.Fatal(err) + } + if len(candles.Candles) != 2 { + t.Fatal("unexpected candle amount") + } + if candles.Interval != kline.FifteenSecond { + t.Error("expected fifteen seconds") + } +} + +func TestShutdown(t *testing.T) { + t.Parallel() + var p Processor + p.mutex.Lock() + p.bufferProcessorInterval = time.Second + p.mutex.Unlock() + var wg sync.WaitGroup + wg.Add(1) + go p.Run(&wg) + wg.Wait() + time.Sleep(time.Millisecond) + if atomic.LoadInt32(&p.started) != 1 { + t.Error("expected it to start running") + } + time.Sleep(time.Second * 2) + if atomic.LoadInt32(&p.started) != 0 { + t.Error("expected it to stop running") + } +} + +func TestFilterTradesByTime(t *testing.T) { + t.Parallel() + trades := []Data{ + { + Exchange: "test", + Timestamp: time.Now().Add(-time.Second), + }, + } + trades = FilterTradesByTime(trades, time.Now().Add(-time.Minute), time.Now()) + if len(trades) != 1 { + t.Error("failed to filter") + } + trades = FilterTradesByTime(trades, time.Now().Add(-time.Millisecond), time.Now()) + if len(trades) != 0 { + t.Error("failed to filter") + } +} + +func TestSaveTradesToDatabase(t *testing.T) { + t.Parallel() + err := SaveTradesToDatabase(Data{}) + if err != nil && err.Error() != "exchange name/uuid not set, cannot insert" { + t.Error(err) + } +} + +func TestGetTradesInRange(t *testing.T) { + t.Parallel() + _, err := GetTradesInRange("", "", "", "", time.Time{}, time.Time{}) + if err != nil && err.Error() != "invalid arguments received" { + t.Error(err) + } +} diff --git a/exchanges/trade/trade_types.go b/exchanges/trade/trade_types.go new file mode 100644 index 00000000..40010dd1 --- /dev/null +++ b/exchanges/trade/trade_types.go @@ -0,0 +1,57 @@ +package trade + +import ( + "sync" + "time" + + "github.com/gofrs/uuid" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" +) + +const DefaultProcessorIntervalTime = time.Second * 15 + +var ( + processor Processor + // BufferProcessorIntervalTime is the interval to save trade buffer data to the database. + // Change this by changing the runtime param `-tradeprocessinginterval=15s` + BufferProcessorIntervalTime = DefaultProcessorIntervalTime +) + +// Data defines trade data +type Data struct { + ID uuid.UUID `json:"ID,omitempty"` + TID string + Exchange string + CurrencyPair currency.Pair + AssetType asset.Item + Side order.Side + Price float64 + Amount float64 + Timestamp time.Time +} + +// Processor used for processing trade data in batches +// and saving them to the database +type Processor struct { + mutex sync.Mutex + started int32 + bufferProcessorInterval time.Duration + buffer []Data +} + +// ByDate sorts trades by date ascending +type ByDate []Data + +func (b ByDate) Len() int { + return len(b) +} + +func (b ByDate) Less(i, j int) bool { + return b[i].Timestamp.Before(b[j].Timestamp) +} + +func (b ByDate) Swap(i, j int) { + b[i], b[j] = b[j], b[i] +} diff --git a/exchanges/yobit/yobit.go b/exchanges/yobit/yobit.go index f65bfc5e..a354084b 100644 --- a/exchanges/yobit/yobit.go +++ b/exchanges/yobit/yobit.go @@ -78,24 +78,22 @@ func (y *Yobit) GetDepth(symbol string) (Orderbook, error) { } // GetTrades returns the trades for a specific currency -func (y *Yobit) GetTrades(symbol string, start int64, sortAsc bool) ([]Trades, error) { - type Response struct { - Data map[string][]Trades +func (y *Yobit) GetTrades(symbol string) ([]Trade, error) { + type respDataHolder struct { + Data map[string][]Trade } - v := url.Values{} - if sortAsc { - v.Set("order", "ASC") - } else { - v.Set("order", "DESC") - } - if start != 0 { - v.Set("since", strconv.FormatInt(start, 10)) + var dataHolder respDataHolder + path := y.API.Endpoints.URL + "/" + apiPublicVersion + "/" + publicTrades + "/" + symbol + err := y.SendHTTPRequest(path, &dataHolder.Data) + if err != nil { + return nil, err } - var response Response - path := y.API.Endpoints.URL + "/" + apiPublicVersion + "/" + publicTrades + "/" + symbol + "?" + v.Encode() - return response.Data[symbol], y.SendHTTPRequest(path, &response.Data) + if tr, ok := dataHolder.Data[symbol]; ok { + return tr, nil + } + return nil, nil } // GetAccountInformation returns a users account info @@ -120,7 +118,7 @@ func (y *Yobit) Trade(pair, orderType string, amount, price float64) (int64, err req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) req.Add("rate", strconv.FormatFloat(price, 'f', -1, 64)) - result := Trade{} + result := TradeOrderResponse{} err := y.SendAuthenticatedHTTPRequest(privateTrade, req, &result) if err != nil { diff --git a/exchanges/yobit/yobit_test.go b/exchanges/yobit/yobit_test.go index daef454f..bb971392 100644 --- a/exchanges/yobit/yobit_test.go +++ b/exchanges/yobit/yobit_test.go @@ -45,6 +45,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatal("Yobit setup error", err) } + os.Exit(m.Run()) } @@ -82,7 +83,7 @@ func TestGetDepth(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := y.GetTrades("btc_usd", 0, false) + _, err := y.GetTrades("btc_usd") if err != nil { t.Error("GetTrades() error", err) } @@ -513,3 +514,25 @@ func TestGetDepositAddress(t *testing.T) { } } } + +func TestGetRecentTrades(t *testing.T) { + currencyPair, err := currency.NewPairFromString("btc_usd") + if err != nil { + t.Fatal(err) + } + _, err = y.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + currencyPair, err := currency.NewPairFromString("btc_usd") + if err != nil { + t.Fatal(err) + } + _, err = y.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/yobit/yobit_types.go b/exchanges/yobit/yobit_types.go index 271d988c..a14367ff 100644 --- a/exchanges/yobit/yobit_types.go +++ b/exchanges/yobit/yobit_types.go @@ -34,10 +34,10 @@ type Orderbook struct { Bids [][]float64 `json:"bids"` // buying orders } -// Trades stores trade information -type Trades struct { +// Trade stores trade information +type Trade struct { Type string `json:"type"` - Price float64 `json:"bid"` + Price float64 `json:"price"` Amount float64 `json:"amount"` TID int64 `json:"tid"` Timestamp int64 `json:"timestamp"` @@ -96,8 +96,8 @@ type CancelOrder struct { Error string `json:"error"` } -// Trade stores the trade information -type Trade struct { +// TradeOrderResponse stores the trade information +type TradeOrderResponse struct { Received float64 `json:"received"` Remains float64 `json:"remains"` OrderID float64 `json:"order_id"` diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index 685d4442..763d2b7d 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -3,6 +3,7 @@ package yobit import ( "errors" "math" + "sort" "strconv" "strings" "sync" @@ -20,6 +21,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -325,9 +327,49 @@ func (y *Yobit) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (y *Yobit) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (y *Yobit) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = y.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var resp []trade.Data + var tradeData []Trade + tradeData, err = y.GetTrades(p.String()) + if err != nil { + return nil, err + } + for i := range tradeData { + tradeTS := time.Unix(tradeData[i].Timestamp, 0) + side := order.Buy + if tradeData[i].Type == "ask" { + side = order.Sell + } + resp = append(resp, trade.Data{ + Exchange: y.Name, + TID: strconv.FormatInt(tradeData[i].TID, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: tradeTS, + }) + } + + err = y.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (y *Yobit) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/exchanges/zb/zb.go b/exchanges/zb/zb.go index 3b714a3d..4ec22120 100644 --- a/exchanges/zb/zb.go +++ b/exchanges/zb/zb.go @@ -29,6 +29,7 @@ const ( zbOrder = "order" zbCancelOrder = "cancelOrder" zbTicker = "ticker" + zbTrades = "trades" zbTickers = "allTicker" zbDepth = "depth" zbUnfinishedOrdersIgnoreTradeType = "getUnfinishedOrdersIgnoreTradeType" @@ -169,6 +170,14 @@ func (z *ZB) GetTicker(symbol string) (TickerResponse, error) { return res, err } +// GetTicker returns a ticker for a given symbol +func (z *ZB) GetTrades(symbol string) (TradeHistory, error) { + urlPath := fmt.Sprintf("%s/%s/%s/%s?market=%s", z.API.Endpoints.URL, zbData, zbAPIVersion, zbTrades, symbol) + var res TradeHistory + err := z.SendHTTPRequest(urlPath, &res, request.UnAuth) + return res, err +} + // GetTickers returns ticker data for all supported symbols func (z *ZB) GetTickers() (map[string]TickerChildResponse, error) { urlPath := fmt.Sprintf("%s/%s/%s/%s", z.API.Endpoints.URL, zbData, zbAPIVersion, zbTickers) diff --git a/exchanges/zb/zb_test.go b/exchanges/zb/zb_test.go index 5e5c019b..8912891c 100644 --- a/exchanges/zb/zb_test.go +++ b/exchanges/zb/zb_test.go @@ -976,3 +976,40 @@ func TestValidateCandlesRequest(t *testing.T) { t.Errorf("unexpected result, expected %v, received %v", z.Name, item.Exchange) } } + +func TestGetTrades(t *testing.T) { + t.Parallel() + + trades, err := z.GetTrades("btc_usdt") + if err != nil { + t.Error(err) + } + if len(trades) == 0 { + t.Error("expected results") + } +} + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = z.GetRecentTrades(currencyPair, asset.Spot) + if err != nil { + t.Error(err) + } +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + currencyPair, err := currency.NewPairFromString("btc_usdt") + if err != nil { + t.Fatal(err) + } + _, err = z.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) + if err != nil && err != common.ErrFunctionNotSupported { + t.Error(err) + } +} diff --git a/exchanges/zb/zb_types.go b/exchanges/zb/zb_types.go index 21ac7346..7ae0a1c8 100644 --- a/exchanges/zb/zb_types.go +++ b/exchanges/zb/zb_types.go @@ -228,3 +228,12 @@ var orderSideMap = map[int64]order.Side{ 0: order.Buy, 1: order.Sell, } + +type TradeHistory []struct { + Amount float64 `json:"amount,string"` + Date int64 `json:"date"` + Price float64 `json:"price,string"` + Tid int64 `json:"tid"` + TradeType string `json:"trade_type"` + Type string `json:"type"` +} diff --git a/exchanges/zb/zb_websocket.go b/exchanges/zb/zb_websocket.go index bc453faf..bdc54f74 100644 --- a/exchanges/zb/zb_websocket.go +++ b/exchanges/zb/zb_websocket.go @@ -20,6 +20,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" ) @@ -93,7 +94,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error { return err } case strings.Contains(result.Channel, "ticker"): - cPair := strings.Split(result.Channel, "_") + cPair := strings.Split(result.Channel, currency.UnderscoreDelimiter) var wsTicker WsTicker err := json.Unmarshal(fixedJSON, &wsTicker) if err != nil { @@ -141,7 +142,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error { }) } - channelInfo := strings.Split(result.Channel, "_") + channelInfo := strings.Split(result.Channel, currency.UnderscoreDelimiter) cPair, err := currency.NewPairFromString(channelInfo[0]) if err != nil { return err @@ -159,7 +160,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error { return err } case strings.Contains(result.Channel, "_order"): - cPair := strings.Split(result.Channel, "_") + cPair := strings.Split(result.Channel, currency.UnderscoreDelimiter) var o WsSubmitOrderResponse err := json.Unmarshal(fixedJSON, &o) if err != nil { @@ -189,7 +190,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error { AssetType: a, } case strings.Contains(result.Channel, "_cancelorder"): - cPair := strings.Split(result.Channel, "_") + cPair := strings.Split(result.Channel, currency.UnderscoreDelimiter) var o WsSubmitOrderResponse err := json.Unmarshal(fixedJSON, &o) if err != nil { @@ -214,37 +215,42 @@ func (z *ZB) wsHandleData(respRaw []byte) error { Status: order.Cancelled, } case strings.Contains(result.Channel, "trades"): - var trades WsTrades - err := json.Unmarshal(fixedJSON, &trades) + if !z.IsSaveTradeDataEnabled() { + return nil + } + var tradeData WsTrades + err := json.Unmarshal(fixedJSON, &tradeData) if err != nil { return err } - - for i := range trades.Data { - channelInfo := strings.Split(result.Channel, "_") + var trades []trade.Data + for i := range tradeData.Data { + channelInfo := strings.Split(result.Channel, currency.UnderscoreDelimiter) cPair, err := currency.NewPairFromString(channelInfo[0]) if err != nil { return err } - - tSide, err := order.StringToOrderSide(trades.Data[i].TradeType) + var tSide order.Side + tSide, err = order.StringToOrderSide(tradeData.Data[i].Type) if err != nil { - z.Websocket.DataHandler <- order.ClassificationError{ + return &order.ClassificationError{ Exchange: z.Name, Err: err, } } - z.Websocket.DataHandler <- stream.TradeData{ - Timestamp: time.Unix(trades.Data[i].Date, 0), + trades = append(trades, trade.Data{ + Timestamp: time.Unix(tradeData.Data[i].Date, 0), CurrencyPair: cPair, AssetType: asset.Spot, Exchange: z.Name, - Price: trades.Data[i].Price, - Amount: trades.Data[i].Amount, + Price: tradeData.Data[i].Price, + Amount: tradeData.Data[i].Amount, Side: tSide, - } + TID: strconv.FormatInt(tradeData.Data[i].TID, 10), + }) } + return trade.AddTradesToBuffer(z.Name, trades...) default: z.Websocket.DataHandler <- stream.UnhandledMessageWarning{ Message: z.Name + diff --git a/exchanges/zb/zb_websocket_types.go b/exchanges/zb/zb_websocket_types.go index 29275f48..1b735060 100644 --- a/exchanges/zb/zb_websocket_types.go +++ b/exchanges/zb/zb_websocket_types.go @@ -51,12 +51,12 @@ type WsDepth struct { // WsTrades defines websocket trade data type WsTrades struct { Data []struct { - Amount float64 `json:"amount,string"` - Price float64 `json:"price,string"` - TID interface{} `json:"tid"` - Date int64 `json:"date"` - Type string `json:"type"` - TradeType string `json:"trade_type"` + Amount float64 `json:"amount,string"` + Price float64 `json:"price,string"` + TID int64 `json:"tid"` + Date int64 `json:"date"` + Type string `json:"type"` + TradeType string `json:"trade_type"` } `json:"data"` } diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index ca0928e5..dba5396a 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -3,6 +3,7 @@ package zb import ( "errors" "fmt" + "sort" "strconv" "strings" "sync" @@ -22,6 +23,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -393,9 +395,50 @@ func (z *ZB) GetFundingHistory() ([]exchange.FundHistory, error) { return nil, common.ErrFunctionNotSupported } -// GetExchangeHistory returns historic trade data within the timeframe provided. -func (z *ZB) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) { - return nil, common.ErrNotYetImplemented +// GetRecentTrades returns the most recent trades for a currency and asset +func (z *ZB) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { + var err error + p, err = z.FormatExchangeCurrency(p, assetType) + if err != nil { + return nil, err + } + var tradeData TradeHistory + tradeData, err = z.GetTrades(p.String()) + if err != nil { + return nil, err + } + var resp []trade.Data + for i := range tradeData { + var side order.Side + side, err = order.StringToOrderSide(tradeData[i].Type) + if err != nil { + return nil, err + } + + resp = append(resp, trade.Data{ + Exchange: z.Name, + TID: strconv.FormatInt(tradeData[i].Tid, 10), + CurrencyPair: p, + AssetType: assetType, + Side: side, + Price: tradeData[i].Price, + Amount: tradeData[i].Amount, + Timestamp: time.Unix(tradeData[i].Date, 0), + }) + } + + err = z.AddTradesToBuffer(resp...) + if err != nil { + return nil, err + } + + sort.Sort(trade.ByDate(resp)) + return resp, nil +} + +// GetHistoricTrades returns historic trade data within the timeframe provided +func (z *ZB) GetHistoricTrades(_ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported } // SubmitOrder submits a new order diff --git a/gctrpc/rpc.pb.go b/gctrpc/rpc.pb.go index 4ae70c31..d9c9b82d 100644 --- a/gctrpc/rpc.pb.go +++ b/gctrpc/rpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.23.0 -// protoc v3.6.1 +// protoc-gen-go v1.25.0 +// protoc v3.12.3 // source: rpc.proto package gctrpc @@ -6425,7 +6425,236 @@ func (x *GetAuditEventResponse) GetEvents() []*AuditEvent { return nil } -type GetHistoricCandlesRequest struct { +type GetSavedTradesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"` + AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + Start string `protobuf:"bytes,4,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,5,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *GetSavedTradesRequest) Reset() { + *x = GetSavedTradesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[105] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSavedTradesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSavedTradesRequest) ProtoMessage() {} + +func (x *GetSavedTradesRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[105] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSavedTradesRequest.ProtoReflect.Descriptor instead. +func (*GetSavedTradesRequest) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{105} +} + +func (x *GetSavedTradesRequest) GetExchange() string { + if x != nil { + return x.Exchange + } + return "" +} + +func (x *GetSavedTradesRequest) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *GetSavedTradesRequest) GetAssetType() string { + if x != nil { + return x.AssetType + } + return "" +} + +func (x *GetSavedTradesRequest) GetStart() string { + if x != nil { + return x.Start + } + return "" +} + +func (x *GetSavedTradesRequest) GetEnd() string { + if x != nil { + return x.End + } + return "" +} + +type SavedTrades struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Price float64 `protobuf:"fixed64,1,opt,name=price,proto3" json:"price,omitempty"` + Amount float64 `protobuf:"fixed64,2,opt,name=amount,proto3" json:"amount,omitempty"` + Side string `protobuf:"bytes,3,opt,name=side,proto3" json:"side,omitempty"` + Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + TradeId string `protobuf:"bytes,5,opt,name=trade_id,json=tradeId,proto3" json:"trade_id,omitempty"` +} + +func (x *SavedTrades) Reset() { + *x = SavedTrades{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[106] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SavedTrades) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SavedTrades) ProtoMessage() {} + +func (x *SavedTrades) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[106] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SavedTrades.ProtoReflect.Descriptor instead. +func (*SavedTrades) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{106} +} + +func (x *SavedTrades) GetPrice() float64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *SavedTrades) GetAmount() float64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *SavedTrades) GetSide() string { + if x != nil { + return x.Side + } + return "" +} + +func (x *SavedTrades) GetTimestamp() string { + if x != nil { + return x.Timestamp + } + return "" +} + +func (x *SavedTrades) GetTradeId() string { + if x != nil { + return x.TradeId + } + return "" +} + +type SavedTradesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExchangeName string `protobuf:"bytes,1,opt,name=exchange_name,json=exchangeName,proto3" json:"exchange_name,omitempty"` + Asset string `protobuf:"bytes,2,opt,name=asset,proto3" json:"asset,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"` + Trades []*SavedTrades `protobuf:"bytes,4,rep,name=trades,proto3" json:"trades,omitempty"` +} + +func (x *SavedTradesResponse) Reset() { + *x = SavedTradesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[107] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SavedTradesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SavedTradesResponse) ProtoMessage() {} + +func (x *SavedTradesResponse) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[107] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SavedTradesResponse.ProtoReflect.Descriptor instead. +func (*SavedTradesResponse) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{107} +} + +func (x *SavedTradesResponse) GetExchangeName() string { + if x != nil { + return x.ExchangeName + } + return "" +} + +func (x *SavedTradesResponse) GetAsset() string { + if x != nil { + return x.Asset + } + return "" +} + +func (x *SavedTradesResponse) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *SavedTradesResponse) GetTrades() []*SavedTrades { + if x != nil { + return x.Trades + } + return nil +} + +type ConvertTradesToCandlesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -6433,18 +6662,123 @@ type GetHistoricCandlesRequest struct { Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"` AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - Start int64 `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"` - End int64 `protobuf:"varint,5,opt,name=end,proto3" json:"end,omitempty"` + Start string `protobuf:"bytes,4,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,5,opt,name=end,proto3" json:"end,omitempty"` TimeInterval int64 `protobuf:"varint,6,opt,name=time_interval,json=timeInterval,proto3" json:"time_interval,omitempty"` - ExRequest bool `protobuf:"varint,7,opt,name=ex_request,json=exRequest,proto3" json:"ex_request,omitempty"` - Sync bool `protobuf:"varint,8,opt,name=sync,proto3" json:"sync,omitempty"` - UseDb bool `protobuf:"varint,9,opt,name=use_db,json=useDb,proto3" json:"use_db,omitempty"` + Sync bool `protobuf:"varint,7,opt,name=sync,proto3" json:"sync,omitempty"` + Force bool `protobuf:"varint,8,opt,name=force,proto3" json:"force,omitempty"` +} + +func (x *ConvertTradesToCandlesRequest) Reset() { + *x = ConvertTradesToCandlesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[108] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConvertTradesToCandlesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConvertTradesToCandlesRequest) ProtoMessage() {} + +func (x *ConvertTradesToCandlesRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[108] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConvertTradesToCandlesRequest.ProtoReflect.Descriptor instead. +func (*ConvertTradesToCandlesRequest) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{108} +} + +func (x *ConvertTradesToCandlesRequest) GetExchange() string { + if x != nil { + return x.Exchange + } + return "" +} + +func (x *ConvertTradesToCandlesRequest) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *ConvertTradesToCandlesRequest) GetAssetType() string { + if x != nil { + return x.AssetType + } + return "" +} + +func (x *ConvertTradesToCandlesRequest) GetStart() string { + if x != nil { + return x.Start + } + return "" +} + +func (x *ConvertTradesToCandlesRequest) GetEnd() string { + if x != nil { + return x.End + } + return "" +} + +func (x *ConvertTradesToCandlesRequest) GetTimeInterval() int64 { + if x != nil { + return x.TimeInterval + } + return 0 +} + +func (x *ConvertTradesToCandlesRequest) GetSync() bool { + if x != nil { + return x.Sync + } + return false +} + +func (x *ConvertTradesToCandlesRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + +type GetHistoricCandlesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"` + AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + Start string `protobuf:"bytes,4,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,5,opt,name=end,proto3" json:"end,omitempty"` + TimeInterval int64 `protobuf:"varint,6,opt,name=time_interval,json=timeInterval,proto3" json:"time_interval,omitempty"` + ExRequest bool `protobuf:"varint,7,opt,name=ex_request,json=exRequest,proto3" json:"ex_request,omitempty"` + Sync bool `protobuf:"varint,8,opt,name=sync,proto3" json:"sync,omitempty"` + UseDb bool `protobuf:"varint,9,opt,name=use_db,json=useDb,proto3" json:"use_db,omitempty"` + FillMissingWithTrades bool `protobuf:"varint,10,opt,name=fill_missing_with_trades,json=fillMissingWithTrades,proto3" json:"fill_missing_with_trades,omitempty"` + Force bool `protobuf:"varint,11,opt,name=force,proto3" json:"force,omitempty"` } func (x *GetHistoricCandlesRequest) Reset() { *x = GetHistoricCandlesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[105] + mi := &file_rpc_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6457,7 +6791,7 @@ func (x *GetHistoricCandlesRequest) String() string { func (*GetHistoricCandlesRequest) ProtoMessage() {} func (x *GetHistoricCandlesRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[105] + mi := &file_rpc_proto_msgTypes[109] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6470,7 +6804,7 @@ func (x *GetHistoricCandlesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHistoricCandlesRequest.ProtoReflect.Descriptor instead. func (*GetHistoricCandlesRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{105} + return file_rpc_proto_rawDescGZIP(), []int{109} } func (x *GetHistoricCandlesRequest) GetExchange() string { @@ -6494,18 +6828,18 @@ func (x *GetHistoricCandlesRequest) GetAssetType() string { return "" } -func (x *GetHistoricCandlesRequest) GetStart() int64 { +func (x *GetHistoricCandlesRequest) GetStart() string { if x != nil { return x.Start } - return 0 + return "" } -func (x *GetHistoricCandlesRequest) GetEnd() int64 { +func (x *GetHistoricCandlesRequest) GetEnd() string { if x != nil { return x.End } - return 0 + return "" } func (x *GetHistoricCandlesRequest) GetTimeInterval() int64 { @@ -6536,6 +6870,20 @@ func (x *GetHistoricCandlesRequest) GetUseDb() bool { return false } +func (x *GetHistoricCandlesRequest) GetFillMissingWithTrades() bool { + if x != nil { + return x.FillMissingWithTrades + } + return false +} + +func (x *GetHistoricCandlesRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + type GetHistoricCandlesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6543,8 +6891,8 @@ type GetHistoricCandlesResponse struct { Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"` - Start int64 `protobuf:"varint,3,opt,name=start,proto3" json:"start,omitempty"` - End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"` + Start string `protobuf:"bytes,3,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,4,opt,name=end,proto3" json:"end,omitempty"` Interval string `protobuf:"bytes,6,opt,name=interval,proto3" json:"interval,omitempty"` Candle []*Candle `protobuf:"bytes,5,rep,name=candle,proto3" json:"candle,omitempty"` } @@ -6552,7 +6900,7 @@ type GetHistoricCandlesResponse struct { func (x *GetHistoricCandlesResponse) Reset() { *x = GetHistoricCandlesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[106] + mi := &file_rpc_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6565,7 +6913,7 @@ func (x *GetHistoricCandlesResponse) String() string { func (*GetHistoricCandlesResponse) ProtoMessage() {} func (x *GetHistoricCandlesResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[106] + mi := &file_rpc_proto_msgTypes[110] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6578,7 +6926,7 @@ func (x *GetHistoricCandlesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHistoricCandlesResponse.ProtoReflect.Descriptor instead. func (*GetHistoricCandlesResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{106} + return file_rpc_proto_rawDescGZIP(), []int{110} } func (x *GetHistoricCandlesResponse) GetExchange() string { @@ -6595,18 +6943,18 @@ func (x *GetHistoricCandlesResponse) GetPair() *CurrencyPair { return nil } -func (x *GetHistoricCandlesResponse) GetStart() int64 { +func (x *GetHistoricCandlesResponse) GetStart() string { if x != nil { return x.Start } - return 0 + return "" } -func (x *GetHistoricCandlesResponse) GetEnd() int64 { +func (x *GetHistoricCandlesResponse) GetEnd() string { if x != nil { return x.End } - return 0 + return "" } func (x *GetHistoricCandlesResponse) GetInterval() string { @@ -6628,7 +6976,7 @@ type Candle struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` + Time string `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` Low float64 `protobuf:"fixed64,2,opt,name=low,proto3" json:"low,omitempty"` High float64 `protobuf:"fixed64,3,opt,name=high,proto3" json:"high,omitempty"` Open float64 `protobuf:"fixed64,4,opt,name=open,proto3" json:"open,omitempty"` @@ -6639,7 +6987,7 @@ type Candle struct { func (x *Candle) Reset() { *x = Candle{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[107] + mi := &file_rpc_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6652,7 +7000,7 @@ func (x *Candle) String() string { func (*Candle) ProtoMessage() {} func (x *Candle) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[107] + mi := &file_rpc_proto_msgTypes[111] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6665,14 +7013,14 @@ func (x *Candle) ProtoReflect() protoreflect.Message { // Deprecated: Use Candle.ProtoReflect.Descriptor instead. func (*Candle) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{107} + return file_rpc_proto_rawDescGZIP(), []int{111} } -func (x *Candle) GetTime() int64 { +func (x *Candle) GetTime() string { if x != nil { return x.Time } - return 0 + return "" } func (x *Candle) GetLow() float64 { @@ -6724,7 +7072,7 @@ type AuditEvent struct { func (x *AuditEvent) Reset() { *x = AuditEvent{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[108] + mi := &file_rpc_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6737,7 +7085,7 @@ func (x *AuditEvent) String() string { func (*AuditEvent) ProtoMessage() {} func (x *AuditEvent) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[108] + mi := &file_rpc_proto_msgTypes[112] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6750,7 +7098,7 @@ func (x *AuditEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use AuditEvent.ProtoReflect.Descriptor instead. func (*AuditEvent) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{108} + return file_rpc_proto_rawDescGZIP(), []int{112} } func (x *AuditEvent) GetType() string { @@ -6795,7 +7143,7 @@ type GCTScript struct { func (x *GCTScript) Reset() { *x = GCTScript{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[109] + mi := &file_rpc_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6808,7 +7156,7 @@ func (x *GCTScript) String() string { func (*GCTScript) ProtoMessage() {} func (x *GCTScript) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[109] + mi := &file_rpc_proto_msgTypes[113] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6821,7 +7169,7 @@ func (x *GCTScript) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScript.ProtoReflect.Descriptor instead. func (*GCTScript) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{109} + return file_rpc_proto_rawDescGZIP(), []int{113} } func (x *GCTScript) GetUUID() string { @@ -6863,7 +7211,7 @@ type GCTScriptExecuteRequest struct { func (x *GCTScriptExecuteRequest) Reset() { *x = GCTScriptExecuteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[110] + mi := &file_rpc_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6876,7 +7224,7 @@ func (x *GCTScriptExecuteRequest) String() string { func (*GCTScriptExecuteRequest) ProtoMessage() {} func (x *GCTScriptExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[110] + mi := &file_rpc_proto_msgTypes[114] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6889,7 +7237,7 @@ func (x *GCTScriptExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptExecuteRequest.ProtoReflect.Descriptor instead. func (*GCTScriptExecuteRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{110} + return file_rpc_proto_rawDescGZIP(), []int{114} } func (x *GCTScriptExecuteRequest) GetScript() *GCTScript { @@ -6910,7 +7258,7 @@ type GCTScriptStopRequest struct { func (x *GCTScriptStopRequest) Reset() { *x = GCTScriptStopRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[111] + mi := &file_rpc_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6923,7 +7271,7 @@ func (x *GCTScriptStopRequest) String() string { func (*GCTScriptStopRequest) ProtoMessage() {} func (x *GCTScriptStopRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[111] + mi := &file_rpc_proto_msgTypes[115] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6936,7 +7284,7 @@ func (x *GCTScriptStopRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptStopRequest.ProtoReflect.Descriptor instead. func (*GCTScriptStopRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{111} + return file_rpc_proto_rawDescGZIP(), []int{115} } func (x *GCTScriptStopRequest) GetScript() *GCTScript { @@ -6955,7 +7303,7 @@ type GCTScriptStopAllRequest struct { func (x *GCTScriptStopAllRequest) Reset() { *x = GCTScriptStopAllRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[112] + mi := &file_rpc_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6968,7 +7316,7 @@ func (x *GCTScriptStopAllRequest) String() string { func (*GCTScriptStopAllRequest) ProtoMessage() {} func (x *GCTScriptStopAllRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[112] + mi := &file_rpc_proto_msgTypes[116] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6981,7 +7329,7 @@ func (x *GCTScriptStopAllRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptStopAllRequest.ProtoReflect.Descriptor instead. func (*GCTScriptStopAllRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{112} + return file_rpc_proto_rawDescGZIP(), []int{116} } type GCTScriptStatusRequest struct { @@ -6993,7 +7341,7 @@ type GCTScriptStatusRequest struct { func (x *GCTScriptStatusRequest) Reset() { *x = GCTScriptStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[113] + mi := &file_rpc_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7006,7 +7354,7 @@ func (x *GCTScriptStatusRequest) String() string { func (*GCTScriptStatusRequest) ProtoMessage() {} func (x *GCTScriptStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[113] + mi := &file_rpc_proto_msgTypes[117] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7019,7 +7367,7 @@ func (x *GCTScriptStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptStatusRequest.ProtoReflect.Descriptor instead. func (*GCTScriptStatusRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{113} + return file_rpc_proto_rawDescGZIP(), []int{117} } type GCTScriptListAllRequest struct { @@ -7031,7 +7379,7 @@ type GCTScriptListAllRequest struct { func (x *GCTScriptListAllRequest) Reset() { *x = GCTScriptListAllRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[114] + mi := &file_rpc_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7044,7 +7392,7 @@ func (x *GCTScriptListAllRequest) String() string { func (*GCTScriptListAllRequest) ProtoMessage() {} func (x *GCTScriptListAllRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[114] + mi := &file_rpc_proto_msgTypes[118] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7057,7 +7405,7 @@ func (x *GCTScriptListAllRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptListAllRequest.ProtoReflect.Descriptor instead. func (*GCTScriptListAllRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{114} + return file_rpc_proto_rawDescGZIP(), []int{118} } type GCTScriptUploadRequest struct { @@ -7075,7 +7423,7 @@ type GCTScriptUploadRequest struct { func (x *GCTScriptUploadRequest) Reset() { *x = GCTScriptUploadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[115] + mi := &file_rpc_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7088,7 +7436,7 @@ func (x *GCTScriptUploadRequest) String() string { func (*GCTScriptUploadRequest) ProtoMessage() {} func (x *GCTScriptUploadRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[115] + mi := &file_rpc_proto_msgTypes[119] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7101,7 +7449,7 @@ func (x *GCTScriptUploadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptUploadRequest.ProtoReflect.Descriptor instead. func (*GCTScriptUploadRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{115} + return file_rpc_proto_rawDescGZIP(), []int{119} } func (x *GCTScriptUploadRequest) GetScriptName() string { @@ -7150,7 +7498,7 @@ type GCTScriptReadScriptRequest struct { func (x *GCTScriptReadScriptRequest) Reset() { *x = GCTScriptReadScriptRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[116] + mi := &file_rpc_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7163,7 +7511,7 @@ func (x *GCTScriptReadScriptRequest) String() string { func (*GCTScriptReadScriptRequest) ProtoMessage() {} func (x *GCTScriptReadScriptRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[116] + mi := &file_rpc_proto_msgTypes[120] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7176,7 +7524,7 @@ func (x *GCTScriptReadScriptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptReadScriptRequest.ProtoReflect.Descriptor instead. func (*GCTScriptReadScriptRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{116} + return file_rpc_proto_rawDescGZIP(), []int{120} } func (x *GCTScriptReadScriptRequest) GetScript() *GCTScript { @@ -7197,7 +7545,7 @@ type GCTScriptQueryRequest struct { func (x *GCTScriptQueryRequest) Reset() { *x = GCTScriptQueryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[117] + mi := &file_rpc_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7210,7 +7558,7 @@ func (x *GCTScriptQueryRequest) String() string { func (*GCTScriptQueryRequest) ProtoMessage() {} func (x *GCTScriptQueryRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[117] + mi := &file_rpc_proto_msgTypes[121] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7223,7 +7571,7 @@ func (x *GCTScriptQueryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptQueryRequest.ProtoReflect.Descriptor instead. func (*GCTScriptQueryRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{117} + return file_rpc_proto_rawDescGZIP(), []int{121} } func (x *GCTScriptQueryRequest) GetScript() *GCTScript { @@ -7245,7 +7593,7 @@ type GCTScriptAutoLoadRequest struct { func (x *GCTScriptAutoLoadRequest) Reset() { *x = GCTScriptAutoLoadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[118] + mi := &file_rpc_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7258,7 +7606,7 @@ func (x *GCTScriptAutoLoadRequest) String() string { func (*GCTScriptAutoLoadRequest) ProtoMessage() {} func (x *GCTScriptAutoLoadRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[118] + mi := &file_rpc_proto_msgTypes[122] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7271,7 +7619,7 @@ func (x *GCTScriptAutoLoadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptAutoLoadRequest.ProtoReflect.Descriptor instead. func (*GCTScriptAutoLoadRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{118} + return file_rpc_proto_rawDescGZIP(), []int{122} } func (x *GCTScriptAutoLoadRequest) GetScript() string { @@ -7300,7 +7648,7 @@ type GCTScriptStatusResponse struct { func (x *GCTScriptStatusResponse) Reset() { *x = GCTScriptStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[119] + mi := &file_rpc_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7313,7 +7661,7 @@ func (x *GCTScriptStatusResponse) String() string { func (*GCTScriptStatusResponse) ProtoMessage() {} func (x *GCTScriptStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[119] + mi := &file_rpc_proto_msgTypes[123] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7326,7 +7674,7 @@ func (x *GCTScriptStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptStatusResponse.ProtoReflect.Descriptor instead. func (*GCTScriptStatusResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{119} + return file_rpc_proto_rawDescGZIP(), []int{123} } func (x *GCTScriptStatusResponse) GetStatus() string { @@ -7356,7 +7704,7 @@ type GCTScriptQueryResponse struct { func (x *GCTScriptQueryResponse) Reset() { *x = GCTScriptQueryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[120] + mi := &file_rpc_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7369,7 +7717,7 @@ func (x *GCTScriptQueryResponse) String() string { func (*GCTScriptQueryResponse) ProtoMessage() {} func (x *GCTScriptQueryResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[120] + mi := &file_rpc_proto_msgTypes[124] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7382,7 +7730,7 @@ func (x *GCTScriptQueryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GCTScriptQueryResponse.ProtoReflect.Descriptor instead. func (*GCTScriptQueryResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{120} + return file_rpc_proto_rawDescGZIP(), []int{124} } func (x *GCTScriptQueryResponse) GetStatus() string { @@ -7418,7 +7766,7 @@ type GenericResponse struct { func (x *GenericResponse) Reset() { *x = GenericResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[121] + mi := &file_rpc_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7431,7 +7779,7 @@ func (x *GenericResponse) String() string { func (*GenericResponse) ProtoMessage() {} func (x *GenericResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[121] + mi := &file_rpc_proto_msgTypes[125] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7444,7 +7792,7 @@ func (x *GenericResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GenericResponse.ProtoReflect.Descriptor instead. func (*GenericResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{121} + return file_rpc_proto_rawDescGZIP(), []int{125} } func (x *GenericResponse) GetStatus() string { @@ -7474,7 +7822,7 @@ type SetExchangeAssetRequest struct { func (x *SetExchangeAssetRequest) Reset() { *x = SetExchangeAssetRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[122] + mi := &file_rpc_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7487,7 +7835,7 @@ func (x *SetExchangeAssetRequest) String() string { func (*SetExchangeAssetRequest) ProtoMessage() {} func (x *SetExchangeAssetRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[122] + mi := &file_rpc_proto_msgTypes[126] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7500,7 +7848,7 @@ func (x *SetExchangeAssetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetExchangeAssetRequest.ProtoReflect.Descriptor instead. func (*SetExchangeAssetRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{122} + return file_rpc_proto_rawDescGZIP(), []int{126} } func (x *SetExchangeAssetRequest) GetExchange() string { @@ -7536,7 +7884,7 @@ type SetExchangeAllPairsRequest struct { func (x *SetExchangeAllPairsRequest) Reset() { *x = SetExchangeAllPairsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[123] + mi := &file_rpc_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7549,7 +7897,7 @@ func (x *SetExchangeAllPairsRequest) String() string { func (*SetExchangeAllPairsRequest) ProtoMessage() {} func (x *SetExchangeAllPairsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[123] + mi := &file_rpc_proto_msgTypes[127] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7562,7 +7910,7 @@ func (x *SetExchangeAllPairsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetExchangeAllPairsRequest.ProtoReflect.Descriptor instead. func (*SetExchangeAllPairsRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{123} + return file_rpc_proto_rawDescGZIP(), []int{127} } func (x *SetExchangeAllPairsRequest) GetExchange() string { @@ -7590,7 +7938,7 @@ type UpdateExchangeSupportedPairsRequest struct { func (x *UpdateExchangeSupportedPairsRequest) Reset() { *x = UpdateExchangeSupportedPairsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[124] + mi := &file_rpc_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7603,7 +7951,7 @@ func (x *UpdateExchangeSupportedPairsRequest) String() string { func (*UpdateExchangeSupportedPairsRequest) ProtoMessage() {} func (x *UpdateExchangeSupportedPairsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[124] + mi := &file_rpc_proto_msgTypes[128] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7616,7 +7964,7 @@ func (x *UpdateExchangeSupportedPairsRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use UpdateExchangeSupportedPairsRequest.ProtoReflect.Descriptor instead. func (*UpdateExchangeSupportedPairsRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{124} + return file_rpc_proto_rawDescGZIP(), []int{128} } func (x *UpdateExchangeSupportedPairsRequest) GetExchange() string { @@ -7637,7 +7985,7 @@ type GetExchangeAssetsRequest struct { func (x *GetExchangeAssetsRequest) Reset() { *x = GetExchangeAssetsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[125] + mi := &file_rpc_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7650,7 +7998,7 @@ func (x *GetExchangeAssetsRequest) String() string { func (*GetExchangeAssetsRequest) ProtoMessage() {} func (x *GetExchangeAssetsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[125] + mi := &file_rpc_proto_msgTypes[129] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7663,7 +8011,7 @@ func (x *GetExchangeAssetsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetExchangeAssetsRequest.ProtoReflect.Descriptor instead. func (*GetExchangeAssetsRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{125} + return file_rpc_proto_rawDescGZIP(), []int{129} } func (x *GetExchangeAssetsRequest) GetExchange() string { @@ -7684,7 +8032,7 @@ type GetExchangeAssetsResponse struct { func (x *GetExchangeAssetsResponse) Reset() { *x = GetExchangeAssetsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[126] + mi := &file_rpc_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7697,7 +8045,7 @@ func (x *GetExchangeAssetsResponse) String() string { func (*GetExchangeAssetsResponse) ProtoMessage() {} func (x *GetExchangeAssetsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[126] + mi := &file_rpc_proto_msgTypes[130] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7710,7 +8058,7 @@ func (x *GetExchangeAssetsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetExchangeAssetsResponse.ProtoReflect.Descriptor instead. func (*GetExchangeAssetsResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{126} + return file_rpc_proto_rawDescGZIP(), []int{130} } func (x *GetExchangeAssetsResponse) GetAssets() string { @@ -7731,7 +8079,7 @@ type WebsocketGetInfoRequest struct { func (x *WebsocketGetInfoRequest) Reset() { *x = WebsocketGetInfoRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[127] + mi := &file_rpc_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7744,7 +8092,7 @@ func (x *WebsocketGetInfoRequest) String() string { func (*WebsocketGetInfoRequest) ProtoMessage() {} func (x *WebsocketGetInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[127] + mi := &file_rpc_proto_msgTypes[131] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7757,7 +8105,7 @@ func (x *WebsocketGetInfoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketGetInfoRequest.ProtoReflect.Descriptor instead. func (*WebsocketGetInfoRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{127} + return file_rpc_proto_rawDescGZIP(), []int{131} } func (x *WebsocketGetInfoRequest) GetExchange() string { @@ -7784,7 +8132,7 @@ type WebsocketGetInfoResponse struct { func (x *WebsocketGetInfoResponse) Reset() { *x = WebsocketGetInfoResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[128] + mi := &file_rpc_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7797,7 +8145,7 @@ func (x *WebsocketGetInfoResponse) String() string { func (*WebsocketGetInfoResponse) ProtoMessage() {} func (x *WebsocketGetInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[128] + mi := &file_rpc_proto_msgTypes[132] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7810,7 +8158,7 @@ func (x *WebsocketGetInfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketGetInfoResponse.ProtoReflect.Descriptor instead. func (*WebsocketGetInfoResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{128} + return file_rpc_proto_rawDescGZIP(), []int{132} } func (x *WebsocketGetInfoResponse) GetExchange() string { @@ -7874,7 +8222,7 @@ type WebsocketSetEnabledRequest struct { func (x *WebsocketSetEnabledRequest) Reset() { *x = WebsocketSetEnabledRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[129] + mi := &file_rpc_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7887,7 +8235,7 @@ func (x *WebsocketSetEnabledRequest) String() string { func (*WebsocketSetEnabledRequest) ProtoMessage() {} func (x *WebsocketSetEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[129] + mi := &file_rpc_proto_msgTypes[133] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7900,7 +8248,7 @@ func (x *WebsocketSetEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketSetEnabledRequest.ProtoReflect.Descriptor instead. func (*WebsocketSetEnabledRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{129} + return file_rpc_proto_rawDescGZIP(), []int{133} } func (x *WebsocketSetEnabledRequest) GetExchange() string { @@ -7928,7 +8276,7 @@ type WebsocketGetSubscriptionsRequest struct { func (x *WebsocketGetSubscriptionsRequest) Reset() { *x = WebsocketGetSubscriptionsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[130] + mi := &file_rpc_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7941,7 +8289,7 @@ func (x *WebsocketGetSubscriptionsRequest) String() string { func (*WebsocketGetSubscriptionsRequest) ProtoMessage() {} func (x *WebsocketGetSubscriptionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[130] + mi := &file_rpc_proto_msgTypes[134] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7954,7 +8302,7 @@ func (x *WebsocketGetSubscriptionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketGetSubscriptionsRequest.ProtoReflect.Descriptor instead. func (*WebsocketGetSubscriptionsRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{130} + return file_rpc_proto_rawDescGZIP(), []int{134} } func (x *WebsocketGetSubscriptionsRequest) GetExchange() string { @@ -7978,7 +8326,7 @@ type WebsocketSubscription struct { func (x *WebsocketSubscription) Reset() { *x = WebsocketSubscription{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[131] + mi := &file_rpc_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7991,7 +8339,7 @@ func (x *WebsocketSubscription) String() string { func (*WebsocketSubscription) ProtoMessage() {} func (x *WebsocketSubscription) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[131] + mi := &file_rpc_proto_msgTypes[135] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8004,7 +8352,7 @@ func (x *WebsocketSubscription) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketSubscription.ProtoReflect.Descriptor instead. func (*WebsocketSubscription) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{131} + return file_rpc_proto_rawDescGZIP(), []int{135} } func (x *WebsocketSubscription) GetChannel() string { @@ -8047,7 +8395,7 @@ type WebsocketGetSubscriptionsResponse struct { func (x *WebsocketGetSubscriptionsResponse) Reset() { *x = WebsocketGetSubscriptionsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[132] + mi := &file_rpc_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8060,7 +8408,7 @@ func (x *WebsocketGetSubscriptionsResponse) String() string { func (*WebsocketGetSubscriptionsResponse) ProtoMessage() {} func (x *WebsocketGetSubscriptionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[132] + mi := &file_rpc_proto_msgTypes[136] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8073,7 +8421,7 @@ func (x *WebsocketGetSubscriptionsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use WebsocketGetSubscriptionsResponse.ProtoReflect.Descriptor instead. func (*WebsocketGetSubscriptionsResponse) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{132} + return file_rpc_proto_rawDescGZIP(), []int{136} } func (x *WebsocketGetSubscriptionsResponse) GetExchange() string { @@ -8102,7 +8450,7 @@ type WebsocketSetProxyRequest struct { func (x *WebsocketSetProxyRequest) Reset() { *x = WebsocketSetProxyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[133] + mi := &file_rpc_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8115,7 +8463,7 @@ func (x *WebsocketSetProxyRequest) String() string { func (*WebsocketSetProxyRequest) ProtoMessage() {} func (x *WebsocketSetProxyRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[133] + mi := &file_rpc_proto_msgTypes[137] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8128,7 +8476,7 @@ func (x *WebsocketSetProxyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketSetProxyRequest.ProtoReflect.Descriptor instead. func (*WebsocketSetProxyRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{133} + return file_rpc_proto_rawDescGZIP(), []int{137} } func (x *WebsocketSetProxyRequest) GetExchange() string { @@ -8157,7 +8505,7 @@ type WebsocketSetURLRequest struct { func (x *WebsocketSetURLRequest) Reset() { *x = WebsocketSetURLRequest{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[134] + mi := &file_rpc_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8170,7 +8518,7 @@ func (x *WebsocketSetURLRequest) String() string { func (*WebsocketSetURLRequest) ProtoMessage() {} func (x *WebsocketSetURLRequest) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[134] + mi := &file_rpc_proto_msgTypes[138] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8183,7 +8531,7 @@ func (x *WebsocketSetURLRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WebsocketSetURLRequest.ProtoReflect.Descriptor instead. func (*WebsocketSetURLRequest) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{134} + return file_rpc_proto_rawDescGZIP(), []int{138} } func (x *WebsocketSetURLRequest) GetExchange() string { @@ -8200,6 +8548,306 @@ func (x *WebsocketSetURLRequest) GetUrl() string { return "" } +type FindMissingCandlePeriodsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExchangeName string `protobuf:"bytes,1,opt,name=exchangeName,proto3" json:"exchangeName,omitempty"` + AssetType string `protobuf:"bytes,2,opt,name=assetType,proto3" json:"assetType,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"` + Interval int64 `protobuf:"varint,4,opt,name=interval,proto3" json:"interval,omitempty"` + Start string `protobuf:"bytes,5,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,6,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *FindMissingCandlePeriodsRequest) Reset() { + *x = FindMissingCandlePeriodsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[139] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindMissingCandlePeriodsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindMissingCandlePeriodsRequest) ProtoMessage() {} + +func (x *FindMissingCandlePeriodsRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[139] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindMissingCandlePeriodsRequest.ProtoReflect.Descriptor instead. +func (*FindMissingCandlePeriodsRequest) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{139} +} + +func (x *FindMissingCandlePeriodsRequest) GetExchangeName() string { + if x != nil { + return x.ExchangeName + } + return "" +} + +func (x *FindMissingCandlePeriodsRequest) GetAssetType() string { + if x != nil { + return x.AssetType + } + return "" +} + +func (x *FindMissingCandlePeriodsRequest) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *FindMissingCandlePeriodsRequest) GetInterval() int64 { + if x != nil { + return x.Interval + } + return 0 +} + +func (x *FindMissingCandlePeriodsRequest) GetStart() string { + if x != nil { + return x.Start + } + return "" +} + +func (x *FindMissingCandlePeriodsRequest) GetEnd() string { + if x != nil { + return x.End + } + return "" +} + +type FindMissingTradePeriodsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExchangeName string `protobuf:"bytes,1,opt,name=exchangeName,proto3" json:"exchangeName,omitempty"` + AssetType string `protobuf:"bytes,2,opt,name=assetType,proto3" json:"assetType,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"` + Start string `protobuf:"bytes,4,opt,name=start,proto3" json:"start,omitempty"` + End string `protobuf:"bytes,5,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *FindMissingTradePeriodsRequest) Reset() { + *x = FindMissingTradePeriodsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[140] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindMissingTradePeriodsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindMissingTradePeriodsRequest) ProtoMessage() {} + +func (x *FindMissingTradePeriodsRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[140] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindMissingTradePeriodsRequest.ProtoReflect.Descriptor instead. +func (*FindMissingTradePeriodsRequest) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{140} +} + +func (x *FindMissingTradePeriodsRequest) GetExchangeName() string { + if x != nil { + return x.ExchangeName + } + return "" +} + +func (x *FindMissingTradePeriodsRequest) GetAssetType() string { + if x != nil { + return x.AssetType + } + return "" +} + +func (x *FindMissingTradePeriodsRequest) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *FindMissingTradePeriodsRequest) GetStart() string { + if x != nil { + return x.Start + } + return "" +} + +func (x *FindMissingTradePeriodsRequest) GetEnd() string { + if x != nil { + return x.End + } + return "" +} + +type FindMissingIntervalsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExchangeName string `protobuf:"bytes,1,opt,name=exchangeName,proto3" json:"exchangeName,omitempty"` + AssetType string `protobuf:"bytes,2,opt,name=assetType,proto3" json:"assetType,omitempty"` + Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"` + MissingPeriods []string `protobuf:"bytes,4,rep,name=missingPeriods,proto3" json:"missingPeriods,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` +} + +func (x *FindMissingIntervalsResponse) Reset() { + *x = FindMissingIntervalsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[141] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FindMissingIntervalsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FindMissingIntervalsResponse) ProtoMessage() {} + +func (x *FindMissingIntervalsResponse) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[141] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FindMissingIntervalsResponse.ProtoReflect.Descriptor instead. +func (*FindMissingIntervalsResponse) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{141} +} + +func (x *FindMissingIntervalsResponse) GetExchangeName() string { + if x != nil { + return x.ExchangeName + } + return "" +} + +func (x *FindMissingIntervalsResponse) GetAssetType() string { + if x != nil { + return x.AssetType + } + return "" +} + +func (x *FindMissingIntervalsResponse) GetPair() *CurrencyPair { + if x != nil { + return x.Pair + } + return nil +} + +func (x *FindMissingIntervalsResponse) GetMissingPeriods() []string { + if x != nil { + return x.MissingPeriods + } + return nil +} + +func (x *FindMissingIntervalsResponse) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +type SetExchangeTradeProcessingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` + Status bool `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"` +} + +func (x *SetExchangeTradeProcessingRequest) Reset() { + *x = SetExchangeTradeProcessingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[142] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetExchangeTradeProcessingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetExchangeTradeProcessingRequest) ProtoMessage() {} + +func (x *SetExchangeTradeProcessingRequest) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[142] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetExchangeTradeProcessingRequest.ProtoReflect.Descriptor instead. +func (*SetExchangeTradeProcessingRequest) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{142} +} + +func (x *SetExchangeTradeProcessingRequest) GetExchange() string { + if x != nil { + return x.Exchange + } + return "" +} + +func (x *SetExchangeTradeProcessingRequest) GetStatus() bool { + if x != nil { + return x.Status + } + return false +} + type CancelAllOrdersResponse_Orders struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -8212,7 +8860,7 @@ type CancelAllOrdersResponse_Orders struct { func (x *CancelAllOrdersResponse_Orders) Reset() { *x = CancelAllOrdersResponse_Orders{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[145] + mi := &file_rpc_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8225,7 +8873,7 @@ func (x *CancelAllOrdersResponse_Orders) String() string { func (*CancelAllOrdersResponse_Orders) ProtoMessage() {} func (x *CancelAllOrdersResponse_Orders) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[145] + mi := &file_rpc_proto_msgTypes[153] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9114,8 +9762,38 @@ var file_rpc_proto_rawDesc = []byte{ 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x97, 0x02, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, + 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, + 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, + 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x88, 0x01, 0x0a, + 0x0b, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, + 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x64, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x19, 0x0a, 0x08, + 0x74, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x74, 0x72, 0x61, 0x64, 0x65, 0x49, 0x64, 0x22, 0xa7, 0x01, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, + 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, + 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, + 0x70, 0x61, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, + 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x06, 0x74, 0x72, 0x61, 0x64, 0x65, + 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x72, 0x61, + 0x64, 0x65, 0x73, 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, @@ -9123,689 +9801,811 @@ var file_rpc_proto_rawDesc = []byte{ 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x78, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x5f, - 0x64, 0x62, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x75, 0x73, 0x65, 0x44, 0x62, 0x22, - 0xce, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, - 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, - 0x70, 0x61, 0x69, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x1a, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x64, - 0x6c, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x6f, - 0x77, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x04, 0x68, 0x69, 0x67, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x6f, - 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x22, 0x78, 0x0a, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x22, 0x62, 0x0a, 0x09, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x55, 0x55, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, - 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, - 0x78, 0x74, 0x52, 0x75, 0x6e, 0x22, 0x44, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, + 0xe6, 0x02, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, + 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, + 0x1d, 0x0a, 0x0a, 0x65, 0x78, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x79, + 0x6e, 0x63, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x5f, 0x64, 0x62, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x75, 0x73, 0x65, 0x44, 0x62, 0x12, 0x37, 0x0a, 0x18, 0x66, 0x69, 0x6c, + 0x6c, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x74, + 0x72, 0x61, 0x64, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x69, 0x6c, + 0x6c, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x57, 0x69, 0x74, 0x68, 0x54, 0x72, 0x61, 0x64, + 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, + 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, + 0x6c, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x77, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x6f, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, + 0x67, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x68, 0x69, 0x67, 0x68, 0x12, 0x12, + 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x6f, 0x70, + 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x05, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, + 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x22, 0x78, 0x0a, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x62, 0x0a, 0x09, 0x47, 0x43, + 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x55, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x52, 0x75, 0x6e, 0x22, 0x44, + 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x22, 0x41, 0x0a, 0x14, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, + 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x19, 0x0a, 0x17, + 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa8, 0x01, 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x22, 0x47, 0x0a, 0x1a, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, + 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x41, 0x0a, 0x14, 0x47, - 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x19, - 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, - 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x43, 0x54, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa8, - 0x01, 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6f, - 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x47, 0x0a, 0x1a, 0x47, 0x43, 0x54, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x22, 0x42, 0x0a, 0x15, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x4a, 0x0a, 0x18, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x5e, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x73, 0x22, 0x6f, 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, + 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x42, 0x0a, 0x15, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, - 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x22, 0x3d, 0x0a, 0x0f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, + 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, + 0x4a, 0x0a, 0x18, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, + 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x5e, 0x0a, 0x17, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x63, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, + 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x6f, 0x0a, 0x16, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, + 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3d, 0x0a, 0x0f, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x63, 0x0a, 0x17, 0x53, + 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x22, 0x50, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, + 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x22, 0x41, 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, + 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x36, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x33, 0x0a, + 0x19, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x73, 0x22, 0x35, 0x0a, 0x17, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x50, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x45, 0x78, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x93, 0x02, 0x0a, 0x18, 0x57, 0x65, + 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x17, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6e, + 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, + 0x50, 0x0a, 0x1a, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x22, 0x3e, 0x0a, 0x20, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x41, 0x0a, 0x23, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x36, 0x0a, 0x18, - 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x22, 0x33, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x35, 0x0a, 0x17, 0x57, 0x65, 0x62, - 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x65, 0x22, 0x7b, 0x0a, 0x15, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x84, + 0x01, 0x0a, 0x21, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x22, 0x93, 0x02, 0x0a, 0x18, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, + 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4c, 0x0a, 0x18, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x22, 0x46, 0x0a, 0x16, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x75, - 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x37, 0x0a, 0x17, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x16, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x72, 0x6c, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x55, 0x72, - 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x50, 0x0a, 0x1a, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x0a, 0x20, 0x57, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x7b, 0x0a, 0x15, 0x57, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x21, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x73, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4c, 0x0a, 0x18, - 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, + 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x1f, + 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x43, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x22, 0x0a, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, + 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x65, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, + 0xb4, 0x01, 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, + 0x72, 0x61, 0x64, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x1c, 0x46, 0x69, 0x6e, 0x64, 0x4d, + 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, + 0x61, 0x69, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x65, + 0x72, 0x69, 0x6f, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x22, 0x57, 0x0a, 0x21, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x22, 0x46, 0x0a, 0x16, 0x57, 0x65, - 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, - 0x72, 0x6c, 0x32, 0x8b, 0x3f, 0x0a, 0x0e, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, - 0x72, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x73, 0x62, 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, - 0x68, 0x0a, 0x0f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6a, 0x0a, 0x10, 0x44, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, - 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, - 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x72, 0x70, 0x63, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, - 0x65, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, - 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, - 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x12, 0x6e, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0xa1, 0x46, 0x0a, + 0x0e, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x4f, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, + 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x73, 0x62, + 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, + 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x68, 0x0a, 0x0f, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, + 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x12, 0x6a, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75, + 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, - 0x2a, 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x12, 0x73, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x64, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, + 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, + 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, + 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x73, - 0x12, 0x6c, 0x0a, 0x0e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x57, - 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, - 0x63, 0x6b, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x69, - 0x63, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x62, 0x6f, 0x6f, 0x6b, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x15, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, - 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, - 0x6b, 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, - 0x79, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, - 0x66, 0x6f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, - 0x6c, 0x69, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, - 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, - 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x7f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, - 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, - 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, - 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, - 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, - 0x69, 0x6f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x76, 0x0a, 0x13, 0x41, 0x64, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72, - 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, 0x70, 0x6f, - 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, - 0x2a, 0x12, 0x7f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, - 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, - 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1f, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, - 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, - 0x65, 0x78, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x67, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x72, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, - 0x12, 0x52, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, - 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x17, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x62, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, - 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x69, 0x6d, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, - 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x09, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, - 0x62, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x68, 0x61, 0x6c, 0x65, - 0x42, 0x6f, 0x6d, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x62, 0x6f, 0x6d, - 0x62, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, - 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x72, 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, - 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, - 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x61, 0x6c, 0x6c, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x56, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, - 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65, - 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, - 0x30, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xaa, - 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6c, 0x0a, 0x11, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, - 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, - 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x66, 0x69, 0x61, - 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x8b, 0x01, 0x0a, 0x1b, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, - 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, - 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, - 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x97, 0x01, 0x0a, - 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, - 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x91, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, - 0x65, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x76, - 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x62, 0x79, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, - 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, - 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, - 0x76, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, - 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, - 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, - 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x78, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, - 0x6a, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, - 0x69, 0x72, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x2f, 0x67, 0x65, 0x74, 0x72, 0x70, 0x63, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x12, 0x93, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x27, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x72, 0x65, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, + 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6e, 0x0a, 0x0f, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, - 0x01, 0x12, 0x8c, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, - 0x12, 0x68, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, - 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x67, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x0f, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, - 0x12, 0x78, 0x0a, 0x13, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, - 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x43, - 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x6c, 0x0a, 0x0e, - 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1d, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x0d, 0x47, 0x43, - 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x1c, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, - 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, - 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, - 0x2a, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, - 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x73, - 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, - 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x12, 0x20, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x0f, 0x47, + 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x69, 0x6e, 0x66, 0x6f, + 0x12, 0x73, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, + 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, + 0x54, 0x50, 0x52, 0x65, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x6f, 0x74, 0x70, 0x12, 0x73, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x73, 0x12, 0x6c, 0x0a, 0x0e, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, - 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1b, 0x22, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x7b, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x69, 0x63, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x10, 0x53, 0x65, 0x74, - 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x1f, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, + 0x69, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, + 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x3a, 0x01, + 0x2a, 0x12, 0x5b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x12, + 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x63, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x12, 0x1b, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x10, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, + 0x3a, 0x01, 0x2a, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, + 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, + 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x6b, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x79, 0x0a, 0x14, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x63, 0x0a, + 0x0c, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x1b, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, + 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, + 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, + 0x69, 0x6f, 0x12, 0x7f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, + 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, + 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, + 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x12, 0x76, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, + 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, - 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x73, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x22, 0x2e, 0x67, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, + 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, + 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x16, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1a, 0x2f, + 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, + 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x11, + 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, + 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, + 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x72, 0x61, 0x74, 0x65, 0x73, 0x12, 0x5a, + 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x52, 0x0a, 0x08, 0x47, 0x65, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x62, + 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, + 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, + 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, + 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, + 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, + 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x69, + 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5e, + 0x0a, 0x09, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x12, 0x18, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, + 0x31, 0x2f, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x62, 0x6f, 0x6d, 0x62, 0x3a, 0x01, 0x2a, 0x12, 0x5e, + 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x72, + 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x61, 0x6c, 0x6c, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, + 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, + 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x56, 0x0a, 0x08, 0x41, + 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, + 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x3a, 0x01, 0x2a, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, + 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xaa, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6c, 0x0a, 0x11, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x46, 0x69, 0x61, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, + 0x3a, 0x01, 0x2a, 0x12, 0x8b, 0x01, 0x0a, 0x1b, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x75, + 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x66, + 0x75, 0x6e, 0x64, 0x73, 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, + 0x2a, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, + 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, + 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x97, 0x01, 0x0a, 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, + 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, + 0x12, 0x91, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, + 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, + 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x76, 0x0a, 0x10, 0x53, 0x65, 0x74, + 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, + 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, + 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x01, + 0x2a, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, + 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0f, 0x53, 0x65, 0x74, + 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, + 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, + 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, + 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, + 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x8c, 0x01, 0x0a, 0x1a, + 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x30, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x75, 0x64, 0x69, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, + 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x6b, 0x0a, + 0x0f, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x1c, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x77, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, - 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x73, 0x12, 0x73, 0x0a, 0x10, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x13, 0x57, 0x65, 0x62, - 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x97, - 0x01, 0x0a, 0x19, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, - 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x57, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x20, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, - 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, - 0x65, 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x67, 0x0a, 0x0f, 0x57, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, - 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, + 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x78, 0x0a, 0x13, 0x47, 0x43, + 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x72, 0x65, 0x61, + 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, + 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x6c, 0x0a, 0x0e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, + 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x0d, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x6b, 0x0a, 0x10, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x12, + 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, + 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, + 0x61, 0x64, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, + 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, - 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x75, 0x72, 0x6c, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x22, 0x16, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x6c, + 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x7b, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, + 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x65, 0x74, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x63, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x73, + 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, + 0x73, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, + 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, + 0x2f, 0x73, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, + 0x61, 0x69, 0x72, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x65, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x77, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, + 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x73, + 0x0a, 0x10, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, + 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, + 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x67, 0x65, 0x74, 0x69, + 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x13, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, + 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, + 0x74, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x97, 0x01, 0x0a, 0x19, 0x57, 0x65, 0x62, + 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, + 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, + 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x12, 0x67, 0x0a, 0x0f, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, + 0x74, 0x55, 0x52, 0x4c, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, + 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x75, 0x72, 0x6c, 0x12, 0x69, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, + 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, + 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x69, 0x63, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, + 0x65, 0x73, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, + 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, + 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x87, + 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, + 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, + 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x76, + 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x74, + 0x6f, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x1f, 0x46, 0x69, 0x6e, + 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x76, 0x65, 0x64, 0x43, 0x61, 0x6e, + 0x64, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, + 0x67, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, + 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x1e, 0x46, 0x69, 0x6e, + 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x64, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, + 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, + 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, + 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, + 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x74, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, + 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -9820,7 +10620,7 @@ func file_rpc_proto_rawDescGZIP() []byte { return file_rpc_proto_rawDescData } -var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 149) +var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 157) var file_rpc_proto_goTypes = []interface{}{ (*GetInfoRequest)(nil), // 0: gctrpc.GetInfoRequest (*GetInfoResponse)(nil), // 1: gctrpc.GetInfoResponse @@ -9927,60 +10727,68 @@ var file_rpc_proto_goTypes = []interface{}{ (*GetExchangeTickerStreamRequest)(nil), // 102: gctrpc.GetExchangeTickerStreamRequest (*GetAuditEventRequest)(nil), // 103: gctrpc.GetAuditEventRequest (*GetAuditEventResponse)(nil), // 104: gctrpc.GetAuditEventResponse - (*GetHistoricCandlesRequest)(nil), // 105: gctrpc.GetHistoricCandlesRequest - (*GetHistoricCandlesResponse)(nil), // 106: gctrpc.GetHistoricCandlesResponse - (*Candle)(nil), // 107: gctrpc.Candle - (*AuditEvent)(nil), // 108: gctrpc.AuditEvent - (*GCTScript)(nil), // 109: gctrpc.GCTScript - (*GCTScriptExecuteRequest)(nil), // 110: gctrpc.GCTScriptExecuteRequest - (*GCTScriptStopRequest)(nil), // 111: gctrpc.GCTScriptStopRequest - (*GCTScriptStopAllRequest)(nil), // 112: gctrpc.GCTScriptStopAllRequest - (*GCTScriptStatusRequest)(nil), // 113: gctrpc.GCTScriptStatusRequest - (*GCTScriptListAllRequest)(nil), // 114: gctrpc.GCTScriptListAllRequest - (*GCTScriptUploadRequest)(nil), // 115: gctrpc.GCTScriptUploadRequest - (*GCTScriptReadScriptRequest)(nil), // 116: gctrpc.GCTScriptReadScriptRequest - (*GCTScriptQueryRequest)(nil), // 117: gctrpc.GCTScriptQueryRequest - (*GCTScriptAutoLoadRequest)(nil), // 118: gctrpc.GCTScriptAutoLoadRequest - (*GCTScriptStatusResponse)(nil), // 119: gctrpc.GCTScriptStatusResponse - (*GCTScriptQueryResponse)(nil), // 120: gctrpc.GCTScriptQueryResponse - (*GenericResponse)(nil), // 121: gctrpc.GenericResponse - (*SetExchangeAssetRequest)(nil), // 122: gctrpc.SetExchangeAssetRequest - (*SetExchangeAllPairsRequest)(nil), // 123: gctrpc.SetExchangeAllPairsRequest - (*UpdateExchangeSupportedPairsRequest)(nil), // 124: gctrpc.UpdateExchangeSupportedPairsRequest - (*GetExchangeAssetsRequest)(nil), // 125: gctrpc.GetExchangeAssetsRequest - (*GetExchangeAssetsResponse)(nil), // 126: gctrpc.GetExchangeAssetsResponse - (*WebsocketGetInfoRequest)(nil), // 127: gctrpc.WebsocketGetInfoRequest - (*WebsocketGetInfoResponse)(nil), // 128: gctrpc.WebsocketGetInfoResponse - (*WebsocketSetEnabledRequest)(nil), // 129: gctrpc.WebsocketSetEnabledRequest - (*WebsocketGetSubscriptionsRequest)(nil), // 130: gctrpc.WebsocketGetSubscriptionsRequest - (*WebsocketSubscription)(nil), // 131: gctrpc.WebsocketSubscription - (*WebsocketGetSubscriptionsResponse)(nil), // 132: gctrpc.WebsocketGetSubscriptionsResponse - (*WebsocketSetProxyRequest)(nil), // 133: gctrpc.WebsocketSetProxyRequest - (*WebsocketSetURLRequest)(nil), // 134: gctrpc.WebsocketSetURLRequest - nil, // 135: gctrpc.GetInfoResponse.SubsystemStatusEntry - nil, // 136: gctrpc.GetInfoResponse.RpcEndpointsEntry - nil, // 137: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry - nil, // 138: gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry - nil, // 139: gctrpc.GetRPCEndpointsResponse.EndpointsEntry - nil, // 140: gctrpc.GetExchangeOTPsResponse.OtpCodesEntry - nil, // 141: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry - nil, // 142: gctrpc.OnlineCoins.CoinsEntry - nil, // 143: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry - nil, // 144: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry - (*CancelAllOrdersResponse_Orders)(nil), // 145: gctrpc.CancelAllOrdersResponse.Orders - nil, // 146: gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry - nil, // 147: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry - nil, // 148: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry - (*timestamp.Timestamp)(nil), // 149: google.protobuf.Timestamp + (*GetSavedTradesRequest)(nil), // 105: gctrpc.GetSavedTradesRequest + (*SavedTrades)(nil), // 106: gctrpc.SavedTrades + (*SavedTradesResponse)(nil), // 107: gctrpc.SavedTradesResponse + (*ConvertTradesToCandlesRequest)(nil), // 108: gctrpc.ConvertTradesToCandlesRequest + (*GetHistoricCandlesRequest)(nil), // 109: gctrpc.GetHistoricCandlesRequest + (*GetHistoricCandlesResponse)(nil), // 110: gctrpc.GetHistoricCandlesResponse + (*Candle)(nil), // 111: gctrpc.Candle + (*AuditEvent)(nil), // 112: gctrpc.AuditEvent + (*GCTScript)(nil), // 113: gctrpc.GCTScript + (*GCTScriptExecuteRequest)(nil), // 114: gctrpc.GCTScriptExecuteRequest + (*GCTScriptStopRequest)(nil), // 115: gctrpc.GCTScriptStopRequest + (*GCTScriptStopAllRequest)(nil), // 116: gctrpc.GCTScriptStopAllRequest + (*GCTScriptStatusRequest)(nil), // 117: gctrpc.GCTScriptStatusRequest + (*GCTScriptListAllRequest)(nil), // 118: gctrpc.GCTScriptListAllRequest + (*GCTScriptUploadRequest)(nil), // 119: gctrpc.GCTScriptUploadRequest + (*GCTScriptReadScriptRequest)(nil), // 120: gctrpc.GCTScriptReadScriptRequest + (*GCTScriptQueryRequest)(nil), // 121: gctrpc.GCTScriptQueryRequest + (*GCTScriptAutoLoadRequest)(nil), // 122: gctrpc.GCTScriptAutoLoadRequest + (*GCTScriptStatusResponse)(nil), // 123: gctrpc.GCTScriptStatusResponse + (*GCTScriptQueryResponse)(nil), // 124: gctrpc.GCTScriptQueryResponse + (*GenericResponse)(nil), // 125: gctrpc.GenericResponse + (*SetExchangeAssetRequest)(nil), // 126: gctrpc.SetExchangeAssetRequest + (*SetExchangeAllPairsRequest)(nil), // 127: gctrpc.SetExchangeAllPairsRequest + (*UpdateExchangeSupportedPairsRequest)(nil), // 128: gctrpc.UpdateExchangeSupportedPairsRequest + (*GetExchangeAssetsRequest)(nil), // 129: gctrpc.GetExchangeAssetsRequest + (*GetExchangeAssetsResponse)(nil), // 130: gctrpc.GetExchangeAssetsResponse + (*WebsocketGetInfoRequest)(nil), // 131: gctrpc.WebsocketGetInfoRequest + (*WebsocketGetInfoResponse)(nil), // 132: gctrpc.WebsocketGetInfoResponse + (*WebsocketSetEnabledRequest)(nil), // 133: gctrpc.WebsocketSetEnabledRequest + (*WebsocketGetSubscriptionsRequest)(nil), // 134: gctrpc.WebsocketGetSubscriptionsRequest + (*WebsocketSubscription)(nil), // 135: gctrpc.WebsocketSubscription + (*WebsocketGetSubscriptionsResponse)(nil), // 136: gctrpc.WebsocketGetSubscriptionsResponse + (*WebsocketSetProxyRequest)(nil), // 137: gctrpc.WebsocketSetProxyRequest + (*WebsocketSetURLRequest)(nil), // 138: gctrpc.WebsocketSetURLRequest + (*FindMissingCandlePeriodsRequest)(nil), // 139: gctrpc.FindMissingCandlePeriodsRequest + (*FindMissingTradePeriodsRequest)(nil), // 140: gctrpc.FindMissingTradePeriodsRequest + (*FindMissingIntervalsResponse)(nil), // 141: gctrpc.FindMissingIntervalsResponse + (*SetExchangeTradeProcessingRequest)(nil), // 142: gctrpc.SetExchangeTradeProcessingRequest + nil, // 143: gctrpc.GetInfoResponse.SubsystemStatusEntry + nil, // 144: gctrpc.GetInfoResponse.RpcEndpointsEntry + nil, // 145: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry + nil, // 146: gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry + nil, // 147: gctrpc.GetRPCEndpointsResponse.EndpointsEntry + nil, // 148: gctrpc.GetExchangeOTPsResponse.OtpCodesEntry + nil, // 149: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry + nil, // 150: gctrpc.OnlineCoins.CoinsEntry + nil, // 151: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry + nil, // 152: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry + (*CancelAllOrdersResponse_Orders)(nil), // 153: gctrpc.CancelAllOrdersResponse.Orders + nil, // 154: gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry + nil, // 155: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry + nil, // 156: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry + (*timestamp.Timestamp)(nil), // 157: google.protobuf.Timestamp } var file_rpc_proto_depIdxs = []int32{ - 135, // 0: gctrpc.GetInfoResponse.subsystem_status:type_name -> gctrpc.GetInfoResponse.SubsystemStatusEntry - 136, // 1: gctrpc.GetInfoResponse.rpc_endpoints:type_name -> gctrpc.GetInfoResponse.RpcEndpointsEntry - 137, // 2: gctrpc.GetCommunicationRelayersResponse.communication_relayers:type_name -> gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry - 138, // 3: gctrpc.GetSusbsytemsResponse.subsystems_status:type_name -> gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry - 139, // 4: gctrpc.GetRPCEndpointsResponse.endpoints:type_name -> gctrpc.GetRPCEndpointsResponse.EndpointsEntry - 140, // 5: gctrpc.GetExchangeOTPsResponse.otp_codes:type_name -> gctrpc.GetExchangeOTPsResponse.OtpCodesEntry - 141, // 6: gctrpc.GetExchangeInfoResponse.supported_assets:type_name -> gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry + 143, // 0: gctrpc.GetInfoResponse.subsystem_status:type_name -> gctrpc.GetInfoResponse.SubsystemStatusEntry + 144, // 1: gctrpc.GetInfoResponse.rpc_endpoints:type_name -> gctrpc.GetInfoResponse.RpcEndpointsEntry + 145, // 2: gctrpc.GetCommunicationRelayersResponse.communication_relayers:type_name -> gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry + 146, // 3: gctrpc.GetSusbsytemsResponse.subsystems_status:type_name -> gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry + 147, // 4: gctrpc.GetRPCEndpointsResponse.endpoints:type_name -> gctrpc.GetRPCEndpointsResponse.EndpointsEntry + 148, // 5: gctrpc.GetExchangeOTPsResponse.otp_codes:type_name -> gctrpc.GetExchangeOTPsResponse.OtpCodesEntry + 149, // 6: gctrpc.GetExchangeInfoResponse.supported_assets:type_name -> gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry 21, // 7: gctrpc.GetTickerRequest.pair:type_name -> gctrpc.CurrencyPair 21, // 8: gctrpc.TickerResponse.pair:type_name -> gctrpc.CurrencyPair 22, // 9: gctrpc.Tickers.tickers:type_name -> gctrpc.TickerResponse @@ -9995,12 +10803,12 @@ var file_rpc_proto_depIdxs = []int32{ 33, // 18: gctrpc.GetAccountInfoResponse.accounts:type_name -> gctrpc.Account 38, // 19: gctrpc.GetPortfolioResponse.portfolio:type_name -> gctrpc.PortfolioAddress 43, // 20: gctrpc.OfflineCoins.addresses:type_name -> gctrpc.OfflineCoinSummary - 142, // 21: gctrpc.OnlineCoins.coins:type_name -> gctrpc.OnlineCoins.CoinsEntry + 150, // 21: gctrpc.OnlineCoins.coins:type_name -> gctrpc.OnlineCoins.CoinsEntry 42, // 22: gctrpc.GetPortfolioSummaryResponse.coin_totals:type_name -> gctrpc.Coin 42, // 23: gctrpc.GetPortfolioSummaryResponse.coins_offline:type_name -> gctrpc.Coin - 143, // 24: gctrpc.GetPortfolioSummaryResponse.coins_offline_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry + 151, // 24: gctrpc.GetPortfolioSummaryResponse.coins_offline_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry 42, // 25: gctrpc.GetPortfolioSummaryResponse.coins_online:type_name -> gctrpc.Coin - 144, // 26: gctrpc.GetPortfolioSummaryResponse.coins_online_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry + 152, // 26: gctrpc.GetPortfolioSummaryResponse.coins_online_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry 51, // 27: gctrpc.GetForexProvidersResponse.forex_providers:type_name -> gctrpc.ForexProvider 54, // 28: gctrpc.GetForexRatesResponse.forex_rates:type_name -> gctrpc.ForexRatesConversion 57, // 29: gctrpc.OrderDetails.trades:type_name -> gctrpc.TradeHistory @@ -10013,189 +10821,210 @@ var file_rpc_proto_depIdxs = []int32{ 27, // 36: gctrpc.SimulateOrderResponse.orders:type_name -> gctrpc.OrderbookItem 21, // 37: gctrpc.WhaleBombRequest.pair:type_name -> gctrpc.CurrencyPair 21, // 38: gctrpc.CancelOrderRequest.pair:type_name -> gctrpc.CurrencyPair - 145, // 39: gctrpc.CancelAllOrdersResponse.orders:type_name -> gctrpc.CancelAllOrdersResponse.Orders + 153, // 39: gctrpc.CancelAllOrdersResponse.orders:type_name -> gctrpc.CancelAllOrdersResponse.Orders 71, // 40: gctrpc.GetEventsResponse.condition_params:type_name -> gctrpc.ConditionParams 21, // 41: gctrpc.GetEventsResponse.pair:type_name -> gctrpc.CurrencyPair 71, // 42: gctrpc.AddEventRequest.condition_params:type_name -> gctrpc.ConditionParams 21, // 43: gctrpc.AddEventRequest.pair:type_name -> gctrpc.CurrencyPair - 147, // 44: gctrpc.GetCryptocurrencyDepositAddressesResponse.addresses:type_name -> gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry + 155, // 44: gctrpc.GetCryptocurrencyDepositAddressesResponse.addresses:type_name -> gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry 88, // 45: gctrpc.WithdrawalEventByIDResponse.event:type_name -> gctrpc.WithdrawalEventResponse 88, // 46: gctrpc.WithdrawalEventsByExchangeResponse.event:type_name -> gctrpc.WithdrawalEventResponse 89, // 47: gctrpc.WithdrawalEventResponse.exchange:type_name -> gctrpc.WithdrawlExchangeEvent 90, // 48: gctrpc.WithdrawalEventResponse.request:type_name -> gctrpc.WithdrawalRequestEvent - 149, // 49: gctrpc.WithdrawalEventResponse.created_at:type_name -> google.protobuf.Timestamp - 149, // 50: gctrpc.WithdrawalEventResponse.updated_at:type_name -> google.protobuf.Timestamp + 157, // 49: gctrpc.WithdrawalEventResponse.created_at:type_name -> google.protobuf.Timestamp + 157, // 50: gctrpc.WithdrawalEventResponse.updated_at:type_name -> google.protobuf.Timestamp 91, // 51: gctrpc.WithdrawalRequestEvent.fiat:type_name -> gctrpc.FiatWithdrawalEvent 92, // 52: gctrpc.WithdrawalRequestEvent.crypto:type_name -> gctrpc.CryptoWithdrawalEvent - 148, // 53: gctrpc.GetExchangePairsResponse.supported_assets:type_name -> gctrpc.GetExchangePairsResponse.SupportedAssetsEntry + 156, // 53: gctrpc.GetExchangePairsResponse.supported_assets:type_name -> gctrpc.GetExchangePairsResponse.SupportedAssetsEntry 21, // 54: gctrpc.SetExchangePairRequest.pairs:type_name -> gctrpc.CurrencyPair 21, // 55: gctrpc.GetOrderbookStreamRequest.pair:type_name -> gctrpc.CurrencyPair 21, // 56: gctrpc.GetTickerStreamRequest.pair:type_name -> gctrpc.CurrencyPair - 108, // 57: gctrpc.GetAuditEventResponse.events:type_name -> gctrpc.AuditEvent - 21, // 58: gctrpc.GetHistoricCandlesRequest.pair:type_name -> gctrpc.CurrencyPair - 21, // 59: gctrpc.GetHistoricCandlesResponse.pair:type_name -> gctrpc.CurrencyPair - 107, // 60: gctrpc.GetHistoricCandlesResponse.candle:type_name -> gctrpc.Candle - 109, // 61: gctrpc.GCTScriptExecuteRequest.script:type_name -> gctrpc.GCTScript - 109, // 62: gctrpc.GCTScriptStopRequest.script:type_name -> gctrpc.GCTScript - 109, // 63: gctrpc.GCTScriptReadScriptRequest.script:type_name -> gctrpc.GCTScript - 109, // 64: gctrpc.GCTScriptQueryRequest.script:type_name -> gctrpc.GCTScript - 109, // 65: gctrpc.GCTScriptStatusResponse.scripts:type_name -> gctrpc.GCTScript - 109, // 66: gctrpc.GCTScriptQueryResponse.script:type_name -> gctrpc.GCTScript - 131, // 67: gctrpc.WebsocketGetSubscriptionsResponse.subscriptions:type_name -> gctrpc.WebsocketSubscription - 9, // 68: gctrpc.GetInfoResponse.RpcEndpointsEntry.value:type_name -> gctrpc.RPCEndpoint - 3, // 69: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry.value:type_name -> gctrpc.CommunicationRelayer - 9, // 70: gctrpc.GetRPCEndpointsResponse.EndpointsEntry.value:type_name -> gctrpc.RPCEndpoint - 18, // 71: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported - 44, // 72: gctrpc.OnlineCoins.CoinsEntry.value:type_name -> gctrpc.OnlineCoinSummary - 45, // 73: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry.value:type_name -> gctrpc.OfflineCoins - 46, // 74: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry.value:type_name -> gctrpc.OnlineCoins - 146, // 75: gctrpc.CancelAllOrdersResponse.Orders.order_status:type_name -> gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry - 18, // 76: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported - 0, // 77: gctrpc.GoCryptoTrader.GetInfo:input_type -> gctrpc.GetInfoRequest - 6, // 78: gctrpc.GoCryptoTrader.GetSubsystems:input_type -> gctrpc.GetSubsystemsRequest - 5, // 79: gctrpc.GoCryptoTrader.EnableSubsystem:input_type -> gctrpc.GenericSubsystemRequest - 5, // 80: gctrpc.GoCryptoTrader.DisableSubsystem:input_type -> gctrpc.GenericSubsystemRequest - 8, // 81: gctrpc.GoCryptoTrader.GetRPCEndpoints:input_type -> gctrpc.GetRPCEndpointsRequest - 2, // 82: gctrpc.GoCryptoTrader.GetCommunicationRelayers:input_type -> gctrpc.GetCommunicationRelayersRequest - 12, // 83: gctrpc.GoCryptoTrader.GetExchanges:input_type -> gctrpc.GetExchangesRequest - 11, // 84: gctrpc.GoCryptoTrader.DisableExchange:input_type -> gctrpc.GenericExchangeNameRequest - 11, // 85: gctrpc.GoCryptoTrader.GetExchangeInfo:input_type -> gctrpc.GenericExchangeNameRequest - 11, // 86: gctrpc.GoCryptoTrader.GetExchangeOTPCode:input_type -> gctrpc.GenericExchangeNameRequest - 15, // 87: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:input_type -> gctrpc.GetExchangeOTPsRequest - 11, // 88: gctrpc.GoCryptoTrader.EnableExchange:input_type -> gctrpc.GenericExchangeNameRequest - 20, // 89: gctrpc.GoCryptoTrader.GetTicker:input_type -> gctrpc.GetTickerRequest - 23, // 90: gctrpc.GoCryptoTrader.GetTickers:input_type -> gctrpc.GetTickersRequest - 26, // 91: gctrpc.GoCryptoTrader.GetOrderbook:input_type -> gctrpc.GetOrderbookRequest - 29, // 92: gctrpc.GoCryptoTrader.GetOrderbooks:input_type -> gctrpc.GetOrderbooksRequest - 32, // 93: gctrpc.GoCryptoTrader.GetAccountInfo:input_type -> gctrpc.GetAccountInfoRequest - 32, // 94: gctrpc.GoCryptoTrader.GetAccountInfoStream:input_type -> gctrpc.GetAccountInfoRequest - 36, // 95: gctrpc.GoCryptoTrader.GetConfig:input_type -> gctrpc.GetConfigRequest - 39, // 96: gctrpc.GoCryptoTrader.GetPortfolio:input_type -> gctrpc.GetPortfolioRequest - 41, // 97: gctrpc.GoCryptoTrader.GetPortfolioSummary:input_type -> gctrpc.GetPortfolioSummaryRequest - 48, // 98: gctrpc.GoCryptoTrader.AddPortfolioAddress:input_type -> gctrpc.AddPortfolioAddressRequest - 49, // 99: gctrpc.GoCryptoTrader.RemovePortfolioAddress:input_type -> gctrpc.RemovePortfolioAddressRequest - 50, // 100: gctrpc.GoCryptoTrader.GetForexProviders:input_type -> gctrpc.GetForexProvidersRequest - 53, // 101: gctrpc.GoCryptoTrader.GetForexRates:input_type -> gctrpc.GetForexRatesRequest - 58, // 102: gctrpc.GoCryptoTrader.GetOrders:input_type -> gctrpc.GetOrdersRequest - 60, // 103: gctrpc.GoCryptoTrader.GetOrder:input_type -> gctrpc.GetOrderRequest - 61, // 104: gctrpc.GoCryptoTrader.SubmitOrder:input_type -> gctrpc.SubmitOrderRequest - 64, // 105: gctrpc.GoCryptoTrader.SimulateOrder:input_type -> gctrpc.SimulateOrderRequest - 66, // 106: gctrpc.GoCryptoTrader.WhaleBomb:input_type -> gctrpc.WhaleBombRequest - 67, // 107: gctrpc.GoCryptoTrader.CancelOrder:input_type -> gctrpc.CancelOrderRequest - 68, // 108: gctrpc.GoCryptoTrader.CancelAllOrders:input_type -> gctrpc.CancelAllOrdersRequest - 70, // 109: gctrpc.GoCryptoTrader.GetEvents:input_type -> gctrpc.GetEventsRequest - 73, // 110: gctrpc.GoCryptoTrader.AddEvent:input_type -> gctrpc.AddEventRequest - 75, // 111: gctrpc.GoCryptoTrader.RemoveEvent:input_type -> gctrpc.RemoveEventRequest - 76, // 112: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:input_type -> gctrpc.GetCryptocurrencyDepositAddressesRequest - 78, // 113: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:input_type -> gctrpc.GetCryptocurrencyDepositAddressRequest - 80, // 114: gctrpc.GoCryptoTrader.WithdrawFiatFunds:input_type -> gctrpc.WithdrawFiatRequest - 81, // 115: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:input_type -> gctrpc.WithdrawCryptoRequest - 83, // 116: gctrpc.GoCryptoTrader.WithdrawalEventByID:input_type -> gctrpc.WithdrawalEventByIDRequest - 85, // 117: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:input_type -> gctrpc.WithdrawalEventsByExchangeRequest - 86, // 118: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:input_type -> gctrpc.WithdrawalEventsByDateRequest - 93, // 119: gctrpc.GoCryptoTrader.GetLoggerDetails:input_type -> gctrpc.GetLoggerDetailsRequest - 95, // 120: gctrpc.GoCryptoTrader.SetLoggerDetails:input_type -> gctrpc.SetLoggerDetailsRequest - 96, // 121: gctrpc.GoCryptoTrader.GetExchangePairs:input_type -> gctrpc.GetExchangePairsRequest - 98, // 122: gctrpc.GoCryptoTrader.SetExchangePair:input_type -> gctrpc.SetExchangePairRequest - 99, // 123: gctrpc.GoCryptoTrader.GetOrderbookStream:input_type -> gctrpc.GetOrderbookStreamRequest - 100, // 124: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:input_type -> gctrpc.GetExchangeOrderbookStreamRequest - 101, // 125: gctrpc.GoCryptoTrader.GetTickerStream:input_type -> gctrpc.GetTickerStreamRequest - 102, // 126: gctrpc.GoCryptoTrader.GetExchangeTickerStream:input_type -> gctrpc.GetExchangeTickerStreamRequest - 103, // 127: gctrpc.GoCryptoTrader.GetAuditEvent:input_type -> gctrpc.GetAuditEventRequest - 110, // 128: gctrpc.GoCryptoTrader.GCTScriptExecute:input_type -> gctrpc.GCTScriptExecuteRequest - 115, // 129: gctrpc.GoCryptoTrader.GCTScriptUpload:input_type -> gctrpc.GCTScriptUploadRequest - 116, // 130: gctrpc.GoCryptoTrader.GCTScriptReadScript:input_type -> gctrpc.GCTScriptReadScriptRequest - 113, // 131: gctrpc.GoCryptoTrader.GCTScriptStatus:input_type -> gctrpc.GCTScriptStatusRequest - 117, // 132: gctrpc.GoCryptoTrader.GCTScriptQuery:input_type -> gctrpc.GCTScriptQueryRequest - 111, // 133: gctrpc.GoCryptoTrader.GCTScriptStop:input_type -> gctrpc.GCTScriptStopRequest - 112, // 134: gctrpc.GoCryptoTrader.GCTScriptStopAll:input_type -> gctrpc.GCTScriptStopAllRequest - 114, // 135: gctrpc.GoCryptoTrader.GCTScriptListAll:input_type -> gctrpc.GCTScriptListAllRequest - 118, // 136: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:input_type -> gctrpc.GCTScriptAutoLoadRequest - 105, // 137: gctrpc.GoCryptoTrader.GetHistoricCandles:input_type -> gctrpc.GetHistoricCandlesRequest - 122, // 138: gctrpc.GoCryptoTrader.SetExchangeAsset:input_type -> gctrpc.SetExchangeAssetRequest - 123, // 139: gctrpc.GoCryptoTrader.SetAllExchangePairs:input_type -> gctrpc.SetExchangeAllPairsRequest - 124, // 140: gctrpc.GoCryptoTrader.UpdateExchangeSupportedPairs:input_type -> gctrpc.UpdateExchangeSupportedPairsRequest - 125, // 141: gctrpc.GoCryptoTrader.GetExchangeAssets:input_type -> gctrpc.GetExchangeAssetsRequest - 127, // 142: gctrpc.GoCryptoTrader.WebsocketGetInfo:input_type -> gctrpc.WebsocketGetInfoRequest - 129, // 143: gctrpc.GoCryptoTrader.WebsocketSetEnabled:input_type -> gctrpc.WebsocketSetEnabledRequest - 130, // 144: gctrpc.GoCryptoTrader.WebsocketGetSubscriptions:input_type -> gctrpc.WebsocketGetSubscriptionsRequest - 133, // 145: gctrpc.GoCryptoTrader.WebsocketSetProxy:input_type -> gctrpc.WebsocketSetProxyRequest - 134, // 146: gctrpc.GoCryptoTrader.WebsocketSetURL:input_type -> gctrpc.WebsocketSetURLRequest - 1, // 147: gctrpc.GoCryptoTrader.GetInfo:output_type -> gctrpc.GetInfoResponse - 7, // 148: gctrpc.GoCryptoTrader.GetSubsystems:output_type -> gctrpc.GetSusbsytemsResponse - 121, // 149: gctrpc.GoCryptoTrader.EnableSubsystem:output_type -> gctrpc.GenericResponse - 121, // 150: gctrpc.GoCryptoTrader.DisableSubsystem:output_type -> gctrpc.GenericResponse - 10, // 151: gctrpc.GoCryptoTrader.GetRPCEndpoints:output_type -> gctrpc.GetRPCEndpointsResponse - 4, // 152: gctrpc.GoCryptoTrader.GetCommunicationRelayers:output_type -> gctrpc.GetCommunicationRelayersResponse - 13, // 153: gctrpc.GoCryptoTrader.GetExchanges:output_type -> gctrpc.GetExchangesResponse - 121, // 154: gctrpc.GoCryptoTrader.DisableExchange:output_type -> gctrpc.GenericResponse - 19, // 155: gctrpc.GoCryptoTrader.GetExchangeInfo:output_type -> gctrpc.GetExchangeInfoResponse - 14, // 156: gctrpc.GoCryptoTrader.GetExchangeOTPCode:output_type -> gctrpc.GetExchangeOTPReponse - 16, // 157: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:output_type -> gctrpc.GetExchangeOTPsResponse - 121, // 158: gctrpc.GoCryptoTrader.EnableExchange:output_type -> gctrpc.GenericResponse - 22, // 159: gctrpc.GoCryptoTrader.GetTicker:output_type -> gctrpc.TickerResponse - 25, // 160: gctrpc.GoCryptoTrader.GetTickers:output_type -> gctrpc.GetTickersResponse - 28, // 161: gctrpc.GoCryptoTrader.GetOrderbook:output_type -> gctrpc.OrderbookResponse - 31, // 162: gctrpc.GoCryptoTrader.GetOrderbooks:output_type -> gctrpc.GetOrderbooksResponse - 35, // 163: gctrpc.GoCryptoTrader.GetAccountInfo:output_type -> gctrpc.GetAccountInfoResponse - 35, // 164: gctrpc.GoCryptoTrader.GetAccountInfoStream:output_type -> gctrpc.GetAccountInfoResponse - 37, // 165: gctrpc.GoCryptoTrader.GetConfig:output_type -> gctrpc.GetConfigResponse - 40, // 166: gctrpc.GoCryptoTrader.GetPortfolio:output_type -> gctrpc.GetPortfolioResponse - 47, // 167: gctrpc.GoCryptoTrader.GetPortfolioSummary:output_type -> gctrpc.GetPortfolioSummaryResponse - 121, // 168: gctrpc.GoCryptoTrader.AddPortfolioAddress:output_type -> gctrpc.GenericResponse - 121, // 169: gctrpc.GoCryptoTrader.RemovePortfolioAddress:output_type -> gctrpc.GenericResponse - 52, // 170: gctrpc.GoCryptoTrader.GetForexProviders:output_type -> gctrpc.GetForexProvidersResponse - 55, // 171: gctrpc.GoCryptoTrader.GetForexRates:output_type -> gctrpc.GetForexRatesResponse - 59, // 172: gctrpc.GoCryptoTrader.GetOrders:output_type -> gctrpc.GetOrdersResponse - 56, // 173: gctrpc.GoCryptoTrader.GetOrder:output_type -> gctrpc.OrderDetails - 63, // 174: gctrpc.GoCryptoTrader.SubmitOrder:output_type -> gctrpc.SubmitOrderResponse - 65, // 175: gctrpc.GoCryptoTrader.SimulateOrder:output_type -> gctrpc.SimulateOrderResponse - 65, // 176: gctrpc.GoCryptoTrader.WhaleBomb:output_type -> gctrpc.SimulateOrderResponse - 121, // 177: gctrpc.GoCryptoTrader.CancelOrder:output_type -> gctrpc.GenericResponse - 69, // 178: gctrpc.GoCryptoTrader.CancelAllOrders:output_type -> gctrpc.CancelAllOrdersResponse - 72, // 179: gctrpc.GoCryptoTrader.GetEvents:output_type -> gctrpc.GetEventsResponse - 74, // 180: gctrpc.GoCryptoTrader.AddEvent:output_type -> gctrpc.AddEventResponse - 121, // 181: gctrpc.GoCryptoTrader.RemoveEvent:output_type -> gctrpc.GenericResponse - 77, // 182: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:output_type -> gctrpc.GetCryptocurrencyDepositAddressesResponse - 79, // 183: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:output_type -> gctrpc.GetCryptocurrencyDepositAddressResponse - 82, // 184: gctrpc.GoCryptoTrader.WithdrawFiatFunds:output_type -> gctrpc.WithdrawResponse - 82, // 185: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:output_type -> gctrpc.WithdrawResponse - 84, // 186: gctrpc.GoCryptoTrader.WithdrawalEventByID:output_type -> gctrpc.WithdrawalEventByIDResponse - 87, // 187: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:output_type -> gctrpc.WithdrawalEventsByExchangeResponse - 87, // 188: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:output_type -> gctrpc.WithdrawalEventsByExchangeResponse - 94, // 189: gctrpc.GoCryptoTrader.GetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse - 94, // 190: gctrpc.GoCryptoTrader.SetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse - 97, // 191: gctrpc.GoCryptoTrader.GetExchangePairs:output_type -> gctrpc.GetExchangePairsResponse - 121, // 192: gctrpc.GoCryptoTrader.SetExchangePair:output_type -> gctrpc.GenericResponse - 28, // 193: gctrpc.GoCryptoTrader.GetOrderbookStream:output_type -> gctrpc.OrderbookResponse - 28, // 194: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:output_type -> gctrpc.OrderbookResponse - 22, // 195: gctrpc.GoCryptoTrader.GetTickerStream:output_type -> gctrpc.TickerResponse - 22, // 196: gctrpc.GoCryptoTrader.GetExchangeTickerStream:output_type -> gctrpc.TickerResponse - 104, // 197: gctrpc.GoCryptoTrader.GetAuditEvent:output_type -> gctrpc.GetAuditEventResponse - 121, // 198: gctrpc.GoCryptoTrader.GCTScriptExecute:output_type -> gctrpc.GenericResponse - 121, // 199: gctrpc.GoCryptoTrader.GCTScriptUpload:output_type -> gctrpc.GenericResponse - 120, // 200: gctrpc.GoCryptoTrader.GCTScriptReadScript:output_type -> gctrpc.GCTScriptQueryResponse - 119, // 201: gctrpc.GoCryptoTrader.GCTScriptStatus:output_type -> gctrpc.GCTScriptStatusResponse - 120, // 202: gctrpc.GoCryptoTrader.GCTScriptQuery:output_type -> gctrpc.GCTScriptQueryResponse - 121, // 203: gctrpc.GoCryptoTrader.GCTScriptStop:output_type -> gctrpc.GenericResponse - 121, // 204: gctrpc.GoCryptoTrader.GCTScriptStopAll:output_type -> gctrpc.GenericResponse - 119, // 205: gctrpc.GoCryptoTrader.GCTScriptListAll:output_type -> gctrpc.GCTScriptStatusResponse - 121, // 206: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:output_type -> gctrpc.GenericResponse - 106, // 207: gctrpc.GoCryptoTrader.GetHistoricCandles:output_type -> gctrpc.GetHistoricCandlesResponse - 121, // 208: gctrpc.GoCryptoTrader.SetExchangeAsset:output_type -> gctrpc.GenericResponse - 121, // 209: gctrpc.GoCryptoTrader.SetAllExchangePairs:output_type -> gctrpc.GenericResponse - 121, // 210: gctrpc.GoCryptoTrader.UpdateExchangeSupportedPairs:output_type -> gctrpc.GenericResponse - 126, // 211: gctrpc.GoCryptoTrader.GetExchangeAssets:output_type -> gctrpc.GetExchangeAssetsResponse - 128, // 212: gctrpc.GoCryptoTrader.WebsocketGetInfo:output_type -> gctrpc.WebsocketGetInfoResponse - 121, // 213: gctrpc.GoCryptoTrader.WebsocketSetEnabled:output_type -> gctrpc.GenericResponse - 132, // 214: gctrpc.GoCryptoTrader.WebsocketGetSubscriptions:output_type -> gctrpc.WebsocketGetSubscriptionsResponse - 121, // 215: gctrpc.GoCryptoTrader.WebsocketSetProxy:output_type -> gctrpc.GenericResponse - 121, // 216: gctrpc.GoCryptoTrader.WebsocketSetURL:output_type -> gctrpc.GenericResponse - 147, // [147:217] is the sub-list for method output_type - 77, // [77:147] is the sub-list for method input_type - 77, // [77:77] is the sub-list for extension type_name - 77, // [77:77] is the sub-list for extension extendee - 0, // [0:77] is the sub-list for field type_name + 112, // 57: gctrpc.GetAuditEventResponse.events:type_name -> gctrpc.AuditEvent + 21, // 58: gctrpc.GetSavedTradesRequest.pair:type_name -> gctrpc.CurrencyPair + 21, // 59: gctrpc.SavedTradesResponse.pair:type_name -> gctrpc.CurrencyPair + 106, // 60: gctrpc.SavedTradesResponse.trades:type_name -> gctrpc.SavedTrades + 21, // 61: gctrpc.ConvertTradesToCandlesRequest.pair:type_name -> gctrpc.CurrencyPair + 21, // 62: gctrpc.GetHistoricCandlesRequest.pair:type_name -> gctrpc.CurrencyPair + 21, // 63: gctrpc.GetHistoricCandlesResponse.pair:type_name -> gctrpc.CurrencyPair + 111, // 64: gctrpc.GetHistoricCandlesResponse.candle:type_name -> gctrpc.Candle + 113, // 65: gctrpc.GCTScriptExecuteRequest.script:type_name -> gctrpc.GCTScript + 113, // 66: gctrpc.GCTScriptStopRequest.script:type_name -> gctrpc.GCTScript + 113, // 67: gctrpc.GCTScriptReadScriptRequest.script:type_name -> gctrpc.GCTScript + 113, // 68: gctrpc.GCTScriptQueryRequest.script:type_name -> gctrpc.GCTScript + 113, // 69: gctrpc.GCTScriptStatusResponse.scripts:type_name -> gctrpc.GCTScript + 113, // 70: gctrpc.GCTScriptQueryResponse.script:type_name -> gctrpc.GCTScript + 135, // 71: gctrpc.WebsocketGetSubscriptionsResponse.subscriptions:type_name -> gctrpc.WebsocketSubscription + 21, // 72: gctrpc.FindMissingCandlePeriodsRequest.pair:type_name -> gctrpc.CurrencyPair + 21, // 73: gctrpc.FindMissingTradePeriodsRequest.pair:type_name -> gctrpc.CurrencyPair + 21, // 74: gctrpc.FindMissingIntervalsResponse.pair:type_name -> gctrpc.CurrencyPair + 9, // 75: gctrpc.GetInfoResponse.RpcEndpointsEntry.value:type_name -> gctrpc.RPCEndpoint + 3, // 76: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry.value:type_name -> gctrpc.CommunicationRelayer + 9, // 77: gctrpc.GetRPCEndpointsResponse.EndpointsEntry.value:type_name -> gctrpc.RPCEndpoint + 18, // 78: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported + 44, // 79: gctrpc.OnlineCoins.CoinsEntry.value:type_name -> gctrpc.OnlineCoinSummary + 45, // 80: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry.value:type_name -> gctrpc.OfflineCoins + 46, // 81: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry.value:type_name -> gctrpc.OnlineCoins + 154, // 82: gctrpc.CancelAllOrdersResponse.Orders.order_status:type_name -> gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry + 18, // 83: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported + 0, // 84: gctrpc.GoCryptoTrader.GetInfo:input_type -> gctrpc.GetInfoRequest + 6, // 85: gctrpc.GoCryptoTrader.GetSubsystems:input_type -> gctrpc.GetSubsystemsRequest + 5, // 86: gctrpc.GoCryptoTrader.EnableSubsystem:input_type -> gctrpc.GenericSubsystemRequest + 5, // 87: gctrpc.GoCryptoTrader.DisableSubsystem:input_type -> gctrpc.GenericSubsystemRequest + 8, // 88: gctrpc.GoCryptoTrader.GetRPCEndpoints:input_type -> gctrpc.GetRPCEndpointsRequest + 2, // 89: gctrpc.GoCryptoTrader.GetCommunicationRelayers:input_type -> gctrpc.GetCommunicationRelayersRequest + 12, // 90: gctrpc.GoCryptoTrader.GetExchanges:input_type -> gctrpc.GetExchangesRequest + 11, // 91: gctrpc.GoCryptoTrader.DisableExchange:input_type -> gctrpc.GenericExchangeNameRequest + 11, // 92: gctrpc.GoCryptoTrader.GetExchangeInfo:input_type -> gctrpc.GenericExchangeNameRequest + 11, // 93: gctrpc.GoCryptoTrader.GetExchangeOTPCode:input_type -> gctrpc.GenericExchangeNameRequest + 15, // 94: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:input_type -> gctrpc.GetExchangeOTPsRequest + 11, // 95: gctrpc.GoCryptoTrader.EnableExchange:input_type -> gctrpc.GenericExchangeNameRequest + 20, // 96: gctrpc.GoCryptoTrader.GetTicker:input_type -> gctrpc.GetTickerRequest + 23, // 97: gctrpc.GoCryptoTrader.GetTickers:input_type -> gctrpc.GetTickersRequest + 26, // 98: gctrpc.GoCryptoTrader.GetOrderbook:input_type -> gctrpc.GetOrderbookRequest + 29, // 99: gctrpc.GoCryptoTrader.GetOrderbooks:input_type -> gctrpc.GetOrderbooksRequest + 32, // 100: gctrpc.GoCryptoTrader.GetAccountInfo:input_type -> gctrpc.GetAccountInfoRequest + 32, // 101: gctrpc.GoCryptoTrader.GetAccountInfoStream:input_type -> gctrpc.GetAccountInfoRequest + 36, // 102: gctrpc.GoCryptoTrader.GetConfig:input_type -> gctrpc.GetConfigRequest + 39, // 103: gctrpc.GoCryptoTrader.GetPortfolio:input_type -> gctrpc.GetPortfolioRequest + 41, // 104: gctrpc.GoCryptoTrader.GetPortfolioSummary:input_type -> gctrpc.GetPortfolioSummaryRequest + 48, // 105: gctrpc.GoCryptoTrader.AddPortfolioAddress:input_type -> gctrpc.AddPortfolioAddressRequest + 49, // 106: gctrpc.GoCryptoTrader.RemovePortfolioAddress:input_type -> gctrpc.RemovePortfolioAddressRequest + 50, // 107: gctrpc.GoCryptoTrader.GetForexProviders:input_type -> gctrpc.GetForexProvidersRequest + 53, // 108: gctrpc.GoCryptoTrader.GetForexRates:input_type -> gctrpc.GetForexRatesRequest + 58, // 109: gctrpc.GoCryptoTrader.GetOrders:input_type -> gctrpc.GetOrdersRequest + 60, // 110: gctrpc.GoCryptoTrader.GetOrder:input_type -> gctrpc.GetOrderRequest + 61, // 111: gctrpc.GoCryptoTrader.SubmitOrder:input_type -> gctrpc.SubmitOrderRequest + 64, // 112: gctrpc.GoCryptoTrader.SimulateOrder:input_type -> gctrpc.SimulateOrderRequest + 66, // 113: gctrpc.GoCryptoTrader.WhaleBomb:input_type -> gctrpc.WhaleBombRequest + 67, // 114: gctrpc.GoCryptoTrader.CancelOrder:input_type -> gctrpc.CancelOrderRequest + 68, // 115: gctrpc.GoCryptoTrader.CancelAllOrders:input_type -> gctrpc.CancelAllOrdersRequest + 70, // 116: gctrpc.GoCryptoTrader.GetEvents:input_type -> gctrpc.GetEventsRequest + 73, // 117: gctrpc.GoCryptoTrader.AddEvent:input_type -> gctrpc.AddEventRequest + 75, // 118: gctrpc.GoCryptoTrader.RemoveEvent:input_type -> gctrpc.RemoveEventRequest + 76, // 119: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:input_type -> gctrpc.GetCryptocurrencyDepositAddressesRequest + 78, // 120: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:input_type -> gctrpc.GetCryptocurrencyDepositAddressRequest + 80, // 121: gctrpc.GoCryptoTrader.WithdrawFiatFunds:input_type -> gctrpc.WithdrawFiatRequest + 81, // 122: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:input_type -> gctrpc.WithdrawCryptoRequest + 83, // 123: gctrpc.GoCryptoTrader.WithdrawalEventByID:input_type -> gctrpc.WithdrawalEventByIDRequest + 85, // 124: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:input_type -> gctrpc.WithdrawalEventsByExchangeRequest + 86, // 125: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:input_type -> gctrpc.WithdrawalEventsByDateRequest + 93, // 126: gctrpc.GoCryptoTrader.GetLoggerDetails:input_type -> gctrpc.GetLoggerDetailsRequest + 95, // 127: gctrpc.GoCryptoTrader.SetLoggerDetails:input_type -> gctrpc.SetLoggerDetailsRequest + 96, // 128: gctrpc.GoCryptoTrader.GetExchangePairs:input_type -> gctrpc.GetExchangePairsRequest + 98, // 129: gctrpc.GoCryptoTrader.SetExchangePair:input_type -> gctrpc.SetExchangePairRequest + 99, // 130: gctrpc.GoCryptoTrader.GetOrderbookStream:input_type -> gctrpc.GetOrderbookStreamRequest + 100, // 131: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:input_type -> gctrpc.GetExchangeOrderbookStreamRequest + 101, // 132: gctrpc.GoCryptoTrader.GetTickerStream:input_type -> gctrpc.GetTickerStreamRequest + 102, // 133: gctrpc.GoCryptoTrader.GetExchangeTickerStream:input_type -> gctrpc.GetExchangeTickerStreamRequest + 103, // 134: gctrpc.GoCryptoTrader.GetAuditEvent:input_type -> gctrpc.GetAuditEventRequest + 114, // 135: gctrpc.GoCryptoTrader.GCTScriptExecute:input_type -> gctrpc.GCTScriptExecuteRequest + 119, // 136: gctrpc.GoCryptoTrader.GCTScriptUpload:input_type -> gctrpc.GCTScriptUploadRequest + 120, // 137: gctrpc.GoCryptoTrader.GCTScriptReadScript:input_type -> gctrpc.GCTScriptReadScriptRequest + 117, // 138: gctrpc.GoCryptoTrader.GCTScriptStatus:input_type -> gctrpc.GCTScriptStatusRequest + 121, // 139: gctrpc.GoCryptoTrader.GCTScriptQuery:input_type -> gctrpc.GCTScriptQueryRequest + 115, // 140: gctrpc.GoCryptoTrader.GCTScriptStop:input_type -> gctrpc.GCTScriptStopRequest + 116, // 141: gctrpc.GoCryptoTrader.GCTScriptStopAll:input_type -> gctrpc.GCTScriptStopAllRequest + 118, // 142: gctrpc.GoCryptoTrader.GCTScriptListAll:input_type -> gctrpc.GCTScriptListAllRequest + 122, // 143: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:input_type -> gctrpc.GCTScriptAutoLoadRequest + 109, // 144: gctrpc.GoCryptoTrader.GetHistoricCandles:input_type -> gctrpc.GetHistoricCandlesRequest + 126, // 145: gctrpc.GoCryptoTrader.SetExchangeAsset:input_type -> gctrpc.SetExchangeAssetRequest + 127, // 146: gctrpc.GoCryptoTrader.SetAllExchangePairs:input_type -> gctrpc.SetExchangeAllPairsRequest + 128, // 147: gctrpc.GoCryptoTrader.UpdateExchangeSupportedPairs:input_type -> gctrpc.UpdateExchangeSupportedPairsRequest + 129, // 148: gctrpc.GoCryptoTrader.GetExchangeAssets:input_type -> gctrpc.GetExchangeAssetsRequest + 131, // 149: gctrpc.GoCryptoTrader.WebsocketGetInfo:input_type -> gctrpc.WebsocketGetInfoRequest + 133, // 150: gctrpc.GoCryptoTrader.WebsocketSetEnabled:input_type -> gctrpc.WebsocketSetEnabledRequest + 134, // 151: gctrpc.GoCryptoTrader.WebsocketGetSubscriptions:input_type -> gctrpc.WebsocketGetSubscriptionsRequest + 137, // 152: gctrpc.GoCryptoTrader.WebsocketSetProxy:input_type -> gctrpc.WebsocketSetProxyRequest + 138, // 153: gctrpc.GoCryptoTrader.WebsocketSetURL:input_type -> gctrpc.WebsocketSetURLRequest + 105, // 154: gctrpc.GoCryptoTrader.GetRecentTrades:input_type -> gctrpc.GetSavedTradesRequest + 105, // 155: gctrpc.GoCryptoTrader.GetHistoricTrades:input_type -> gctrpc.GetSavedTradesRequest + 105, // 156: gctrpc.GoCryptoTrader.GetSavedTrades:input_type -> gctrpc.GetSavedTradesRequest + 108, // 157: gctrpc.GoCryptoTrader.ConvertTradesToCandles:input_type -> gctrpc.ConvertTradesToCandlesRequest + 139, // 158: gctrpc.GoCryptoTrader.FindMissingSavedCandleIntervals:input_type -> gctrpc.FindMissingCandlePeriodsRequest + 140, // 159: gctrpc.GoCryptoTrader.FindMissingSavedTradeIntervals:input_type -> gctrpc.FindMissingTradePeriodsRequest + 142, // 160: gctrpc.GoCryptoTrader.SetExchangeTradeProcessing:input_type -> gctrpc.SetExchangeTradeProcessingRequest + 1, // 161: gctrpc.GoCryptoTrader.GetInfo:output_type -> gctrpc.GetInfoResponse + 7, // 162: gctrpc.GoCryptoTrader.GetSubsystems:output_type -> gctrpc.GetSusbsytemsResponse + 125, // 163: gctrpc.GoCryptoTrader.EnableSubsystem:output_type -> gctrpc.GenericResponse + 125, // 164: gctrpc.GoCryptoTrader.DisableSubsystem:output_type -> gctrpc.GenericResponse + 10, // 165: gctrpc.GoCryptoTrader.GetRPCEndpoints:output_type -> gctrpc.GetRPCEndpointsResponse + 4, // 166: gctrpc.GoCryptoTrader.GetCommunicationRelayers:output_type -> gctrpc.GetCommunicationRelayersResponse + 13, // 167: gctrpc.GoCryptoTrader.GetExchanges:output_type -> gctrpc.GetExchangesResponse + 125, // 168: gctrpc.GoCryptoTrader.DisableExchange:output_type -> gctrpc.GenericResponse + 19, // 169: gctrpc.GoCryptoTrader.GetExchangeInfo:output_type -> gctrpc.GetExchangeInfoResponse + 14, // 170: gctrpc.GoCryptoTrader.GetExchangeOTPCode:output_type -> gctrpc.GetExchangeOTPReponse + 16, // 171: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:output_type -> gctrpc.GetExchangeOTPsResponse + 125, // 172: gctrpc.GoCryptoTrader.EnableExchange:output_type -> gctrpc.GenericResponse + 22, // 173: gctrpc.GoCryptoTrader.GetTicker:output_type -> gctrpc.TickerResponse + 25, // 174: gctrpc.GoCryptoTrader.GetTickers:output_type -> gctrpc.GetTickersResponse + 28, // 175: gctrpc.GoCryptoTrader.GetOrderbook:output_type -> gctrpc.OrderbookResponse + 31, // 176: gctrpc.GoCryptoTrader.GetOrderbooks:output_type -> gctrpc.GetOrderbooksResponse + 35, // 177: gctrpc.GoCryptoTrader.GetAccountInfo:output_type -> gctrpc.GetAccountInfoResponse + 35, // 178: gctrpc.GoCryptoTrader.GetAccountInfoStream:output_type -> gctrpc.GetAccountInfoResponse + 37, // 179: gctrpc.GoCryptoTrader.GetConfig:output_type -> gctrpc.GetConfigResponse + 40, // 180: gctrpc.GoCryptoTrader.GetPortfolio:output_type -> gctrpc.GetPortfolioResponse + 47, // 181: gctrpc.GoCryptoTrader.GetPortfolioSummary:output_type -> gctrpc.GetPortfolioSummaryResponse + 125, // 182: gctrpc.GoCryptoTrader.AddPortfolioAddress:output_type -> gctrpc.GenericResponse + 125, // 183: gctrpc.GoCryptoTrader.RemovePortfolioAddress:output_type -> gctrpc.GenericResponse + 52, // 184: gctrpc.GoCryptoTrader.GetForexProviders:output_type -> gctrpc.GetForexProvidersResponse + 55, // 185: gctrpc.GoCryptoTrader.GetForexRates:output_type -> gctrpc.GetForexRatesResponse + 59, // 186: gctrpc.GoCryptoTrader.GetOrders:output_type -> gctrpc.GetOrdersResponse + 56, // 187: gctrpc.GoCryptoTrader.GetOrder:output_type -> gctrpc.OrderDetails + 63, // 188: gctrpc.GoCryptoTrader.SubmitOrder:output_type -> gctrpc.SubmitOrderResponse + 65, // 189: gctrpc.GoCryptoTrader.SimulateOrder:output_type -> gctrpc.SimulateOrderResponse + 65, // 190: gctrpc.GoCryptoTrader.WhaleBomb:output_type -> gctrpc.SimulateOrderResponse + 125, // 191: gctrpc.GoCryptoTrader.CancelOrder:output_type -> gctrpc.GenericResponse + 69, // 192: gctrpc.GoCryptoTrader.CancelAllOrders:output_type -> gctrpc.CancelAllOrdersResponse + 72, // 193: gctrpc.GoCryptoTrader.GetEvents:output_type -> gctrpc.GetEventsResponse + 74, // 194: gctrpc.GoCryptoTrader.AddEvent:output_type -> gctrpc.AddEventResponse + 125, // 195: gctrpc.GoCryptoTrader.RemoveEvent:output_type -> gctrpc.GenericResponse + 77, // 196: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:output_type -> gctrpc.GetCryptocurrencyDepositAddressesResponse + 79, // 197: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:output_type -> gctrpc.GetCryptocurrencyDepositAddressResponse + 82, // 198: gctrpc.GoCryptoTrader.WithdrawFiatFunds:output_type -> gctrpc.WithdrawResponse + 82, // 199: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:output_type -> gctrpc.WithdrawResponse + 84, // 200: gctrpc.GoCryptoTrader.WithdrawalEventByID:output_type -> gctrpc.WithdrawalEventByIDResponse + 87, // 201: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:output_type -> gctrpc.WithdrawalEventsByExchangeResponse + 87, // 202: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:output_type -> gctrpc.WithdrawalEventsByExchangeResponse + 94, // 203: gctrpc.GoCryptoTrader.GetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse + 94, // 204: gctrpc.GoCryptoTrader.SetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse + 97, // 205: gctrpc.GoCryptoTrader.GetExchangePairs:output_type -> gctrpc.GetExchangePairsResponse + 125, // 206: gctrpc.GoCryptoTrader.SetExchangePair:output_type -> gctrpc.GenericResponse + 28, // 207: gctrpc.GoCryptoTrader.GetOrderbookStream:output_type -> gctrpc.OrderbookResponse + 28, // 208: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:output_type -> gctrpc.OrderbookResponse + 22, // 209: gctrpc.GoCryptoTrader.GetTickerStream:output_type -> gctrpc.TickerResponse + 22, // 210: gctrpc.GoCryptoTrader.GetExchangeTickerStream:output_type -> gctrpc.TickerResponse + 104, // 211: gctrpc.GoCryptoTrader.GetAuditEvent:output_type -> gctrpc.GetAuditEventResponse + 125, // 212: gctrpc.GoCryptoTrader.GCTScriptExecute:output_type -> gctrpc.GenericResponse + 125, // 213: gctrpc.GoCryptoTrader.GCTScriptUpload:output_type -> gctrpc.GenericResponse + 124, // 214: gctrpc.GoCryptoTrader.GCTScriptReadScript:output_type -> gctrpc.GCTScriptQueryResponse + 123, // 215: gctrpc.GoCryptoTrader.GCTScriptStatus:output_type -> gctrpc.GCTScriptStatusResponse + 124, // 216: gctrpc.GoCryptoTrader.GCTScriptQuery:output_type -> gctrpc.GCTScriptQueryResponse + 125, // 217: gctrpc.GoCryptoTrader.GCTScriptStop:output_type -> gctrpc.GenericResponse + 125, // 218: gctrpc.GoCryptoTrader.GCTScriptStopAll:output_type -> gctrpc.GenericResponse + 123, // 219: gctrpc.GoCryptoTrader.GCTScriptListAll:output_type -> gctrpc.GCTScriptStatusResponse + 125, // 220: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:output_type -> gctrpc.GenericResponse + 110, // 221: gctrpc.GoCryptoTrader.GetHistoricCandles:output_type -> gctrpc.GetHistoricCandlesResponse + 125, // 222: gctrpc.GoCryptoTrader.SetExchangeAsset:output_type -> gctrpc.GenericResponse + 125, // 223: gctrpc.GoCryptoTrader.SetAllExchangePairs:output_type -> gctrpc.GenericResponse + 125, // 224: gctrpc.GoCryptoTrader.UpdateExchangeSupportedPairs:output_type -> gctrpc.GenericResponse + 130, // 225: gctrpc.GoCryptoTrader.GetExchangeAssets:output_type -> gctrpc.GetExchangeAssetsResponse + 132, // 226: gctrpc.GoCryptoTrader.WebsocketGetInfo:output_type -> gctrpc.WebsocketGetInfoResponse + 125, // 227: gctrpc.GoCryptoTrader.WebsocketSetEnabled:output_type -> gctrpc.GenericResponse + 136, // 228: gctrpc.GoCryptoTrader.WebsocketGetSubscriptions:output_type -> gctrpc.WebsocketGetSubscriptionsResponse + 125, // 229: gctrpc.GoCryptoTrader.WebsocketSetProxy:output_type -> gctrpc.GenericResponse + 125, // 230: gctrpc.GoCryptoTrader.WebsocketSetURL:output_type -> gctrpc.GenericResponse + 107, // 231: gctrpc.GoCryptoTrader.GetRecentTrades:output_type -> gctrpc.SavedTradesResponse + 107, // 232: gctrpc.GoCryptoTrader.GetHistoricTrades:output_type -> gctrpc.SavedTradesResponse + 107, // 233: gctrpc.GoCryptoTrader.GetSavedTrades:output_type -> gctrpc.SavedTradesResponse + 110, // 234: gctrpc.GoCryptoTrader.ConvertTradesToCandles:output_type -> gctrpc.GetHistoricCandlesResponse + 141, // 235: gctrpc.GoCryptoTrader.FindMissingSavedCandleIntervals:output_type -> gctrpc.FindMissingIntervalsResponse + 141, // 236: gctrpc.GoCryptoTrader.FindMissingSavedTradeIntervals:output_type -> gctrpc.FindMissingIntervalsResponse + 125, // 237: gctrpc.GoCryptoTrader.SetExchangeTradeProcessing:output_type -> gctrpc.GenericResponse + 161, // [161:238] is the sub-list for method output_type + 84, // [84:161] is the sub-list for method input_type + 84, // [84:84] is the sub-list for extension type_name + 84, // [84:84] is the sub-list for extension extendee + 0, // [0:84] is the sub-list for field type_name } func init() { file_rpc_proto_init() } @@ -11465,7 +12294,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetHistoricCandlesRequest); i { + switch v := v.(*GetSavedTradesRequest); i { case 0: return &v.state case 1: @@ -11477,7 +12306,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetHistoricCandlesResponse); i { + switch v := v.(*SavedTrades); i { case 0: return &v.state case 1: @@ -11489,7 +12318,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Candle); i { + switch v := v.(*SavedTradesResponse); i { case 0: return &v.state case 1: @@ -11501,7 +12330,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuditEvent); i { + switch v := v.(*ConvertTradesToCandlesRequest); i { case 0: return &v.state case 1: @@ -11513,7 +12342,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[109].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScript); i { + switch v := v.(*GetHistoricCandlesRequest); i { case 0: return &v.state case 1: @@ -11525,7 +12354,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptExecuteRequest); i { + switch v := v.(*GetHistoricCandlesResponse); i { case 0: return &v.state case 1: @@ -11537,7 +12366,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptStopRequest); i { + switch v := v.(*Candle); i { case 0: return &v.state case 1: @@ -11549,7 +12378,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptStopAllRequest); i { + switch v := v.(*AuditEvent); i { case 0: return &v.state case 1: @@ -11561,7 +12390,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[113].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptStatusRequest); i { + switch v := v.(*GCTScript); i { case 0: return &v.state case 1: @@ -11573,7 +12402,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptListAllRequest); i { + switch v := v.(*GCTScriptExecuteRequest); i { case 0: return &v.state case 1: @@ -11585,7 +12414,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptUploadRequest); i { + switch v := v.(*GCTScriptStopRequest); i { case 0: return &v.state case 1: @@ -11597,7 +12426,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[116].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptReadScriptRequest); i { + switch v := v.(*GCTScriptStopAllRequest); i { case 0: return &v.state case 1: @@ -11609,7 +12438,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[117].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptQueryRequest); i { + switch v := v.(*GCTScriptStatusRequest); i { case 0: return &v.state case 1: @@ -11621,7 +12450,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[118].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptAutoLoadRequest); i { + switch v := v.(*GCTScriptListAllRequest); i { case 0: return &v.state case 1: @@ -11633,7 +12462,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[119].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptStatusResponse); i { + switch v := v.(*GCTScriptUploadRequest); i { case 0: return &v.state case 1: @@ -11645,7 +12474,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[120].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GCTScriptQueryResponse); i { + switch v := v.(*GCTScriptReadScriptRequest); i { case 0: return &v.state case 1: @@ -11657,7 +12486,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[121].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenericResponse); i { + switch v := v.(*GCTScriptQueryRequest); i { case 0: return &v.state case 1: @@ -11669,7 +12498,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[122].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetExchangeAssetRequest); i { + switch v := v.(*GCTScriptAutoLoadRequest); i { case 0: return &v.state case 1: @@ -11681,7 +12510,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[123].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetExchangeAllPairsRequest); i { + switch v := v.(*GCTScriptStatusResponse); i { case 0: return &v.state case 1: @@ -11693,7 +12522,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[124].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateExchangeSupportedPairsRequest); i { + switch v := v.(*GCTScriptQueryResponse); i { case 0: return &v.state case 1: @@ -11705,7 +12534,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[125].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetExchangeAssetsRequest); i { + switch v := v.(*GenericResponse); i { case 0: return &v.state case 1: @@ -11717,7 +12546,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[126].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetExchangeAssetsResponse); i { + switch v := v.(*SetExchangeAssetRequest); i { case 0: return &v.state case 1: @@ -11729,7 +12558,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[127].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketGetInfoRequest); i { + switch v := v.(*SetExchangeAllPairsRequest); i { case 0: return &v.state case 1: @@ -11741,7 +12570,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[128].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketGetInfoResponse); i { + switch v := v.(*UpdateExchangeSupportedPairsRequest); i { case 0: return &v.state case 1: @@ -11753,7 +12582,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[129].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketSetEnabledRequest); i { + switch v := v.(*GetExchangeAssetsRequest); i { case 0: return &v.state case 1: @@ -11765,7 +12594,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[130].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketGetSubscriptionsRequest); i { + switch v := v.(*GetExchangeAssetsResponse); i { case 0: return &v.state case 1: @@ -11777,7 +12606,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[131].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketSubscription); i { + switch v := v.(*WebsocketGetInfoRequest); i { case 0: return &v.state case 1: @@ -11789,7 +12618,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[132].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketGetSubscriptionsResponse); i { + switch v := v.(*WebsocketGetInfoResponse); i { case 0: return &v.state case 1: @@ -11801,7 +12630,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[133].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebsocketSetProxyRequest); i { + switch v := v.(*WebsocketSetEnabledRequest); i { case 0: return &v.state case 1: @@ -11813,6 +12642,54 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[134].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebsocketGetSubscriptionsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[135].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebsocketSubscription); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[136].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebsocketGetSubscriptionsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[137].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WebsocketSetProxyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[138].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WebsocketSetURLRequest); i { case 0: return &v.state @@ -11824,7 +12701,55 @@ func file_rpc_proto_init() { return nil } } - file_rpc_proto_msgTypes[145].Exporter = func(v interface{}, i int) interface{} { + file_rpc_proto_msgTypes[139].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindMissingCandlePeriodsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[140].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindMissingTradePeriodsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[141].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FindMissingIntervalsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[142].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetExchangeTradeProcessingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[153].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CancelAllOrdersResponse_Orders); i { case 0: return &v.state @@ -11843,7 +12768,7 @@ func file_rpc_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_rpc_proto_rawDesc, NumEnums: 0, - NumMessages: 149, + NumMessages: 157, NumExtensions: 0, NumServices: 1, }, @@ -11939,6 +12864,13 @@ type GoCryptoTraderClient interface { WebsocketGetSubscriptions(ctx context.Context, in *WebsocketGetSubscriptionsRequest, opts ...grpc.CallOption) (*WebsocketGetSubscriptionsResponse, error) WebsocketSetProxy(ctx context.Context, in *WebsocketSetProxyRequest, opts ...grpc.CallOption) (*GenericResponse, error) WebsocketSetURL(ctx context.Context, in *WebsocketSetURLRequest, opts ...grpc.CallOption) (*GenericResponse, error) + GetRecentTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (*SavedTradesResponse, error) + GetHistoricTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetHistoricTradesClient, error) + GetSavedTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (*SavedTradesResponse, error) + ConvertTradesToCandles(ctx context.Context, in *ConvertTradesToCandlesRequest, opts ...grpc.CallOption) (*GetHistoricCandlesResponse, error) + FindMissingSavedCandleIntervals(ctx context.Context, in *FindMissingCandlePeriodsRequest, opts ...grpc.CallOption) (*FindMissingIntervalsResponse, error) + FindMissingSavedTradeIntervals(ctx context.Context, in *FindMissingTradePeriodsRequest, opts ...grpc.CallOption) (*FindMissingIntervalsResponse, error) + SetExchangeTradeProcessing(ctx context.Context, in *SetExchangeTradeProcessingRequest, opts ...grpc.CallOption) (*GenericResponse, error) } type goCryptoTraderClient struct { @@ -12694,6 +13626,92 @@ func (c *goCryptoTraderClient) WebsocketSetURL(ctx context.Context, in *Websocke return out, nil } +func (c *goCryptoTraderClient) GetRecentTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (*SavedTradesResponse, error) { + out := new(SavedTradesResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GetRecentTrades", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *goCryptoTraderClient) GetHistoricTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetHistoricTradesClient, error) { + stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[5], "/gctrpc.GoCryptoTrader/GetHistoricTrades", opts...) + if err != nil { + return nil, err + } + x := &goCryptoTraderGetHistoricTradesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GoCryptoTrader_GetHistoricTradesClient interface { + Recv() (*SavedTradesResponse, error) + grpc.ClientStream +} + +type goCryptoTraderGetHistoricTradesClient struct { + grpc.ClientStream +} + +func (x *goCryptoTraderGetHistoricTradesClient) Recv() (*SavedTradesResponse, error) { + m := new(SavedTradesResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *goCryptoTraderClient) GetSavedTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (*SavedTradesResponse, error) { + out := new(SavedTradesResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GetSavedTrades", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *goCryptoTraderClient) ConvertTradesToCandles(ctx context.Context, in *ConvertTradesToCandlesRequest, opts ...grpc.CallOption) (*GetHistoricCandlesResponse, error) { + out := new(GetHistoricCandlesResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/ConvertTradesToCandles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *goCryptoTraderClient) FindMissingSavedCandleIntervals(ctx context.Context, in *FindMissingCandlePeriodsRequest, opts ...grpc.CallOption) (*FindMissingIntervalsResponse, error) { + out := new(FindMissingIntervalsResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *goCryptoTraderClient) FindMissingSavedTradeIntervals(ctx context.Context, in *FindMissingTradePeriodsRequest, opts ...grpc.CallOption) (*FindMissingIntervalsResponse, error) { + out := new(FindMissingIntervalsResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *goCryptoTraderClient) SetExchangeTradeProcessing(ctx context.Context, in *SetExchangeTradeProcessingRequest, opts ...grpc.CallOption) (*GenericResponse, error) { + out := new(GenericResponse) + err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // GoCryptoTraderServer is the server API for GoCryptoTrader service. type GoCryptoTraderServer interface { GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) @@ -12766,6 +13784,13 @@ type GoCryptoTraderServer interface { WebsocketGetSubscriptions(context.Context, *WebsocketGetSubscriptionsRequest) (*WebsocketGetSubscriptionsResponse, error) WebsocketSetProxy(context.Context, *WebsocketSetProxyRequest) (*GenericResponse, error) WebsocketSetURL(context.Context, *WebsocketSetURLRequest) (*GenericResponse, error) + GetRecentTrades(context.Context, *GetSavedTradesRequest) (*SavedTradesResponse, error) + GetHistoricTrades(*GetSavedTradesRequest, GoCryptoTrader_GetHistoricTradesServer) error + GetSavedTrades(context.Context, *GetSavedTradesRequest) (*SavedTradesResponse, error) + ConvertTradesToCandles(context.Context, *ConvertTradesToCandlesRequest) (*GetHistoricCandlesResponse, error) + FindMissingSavedCandleIntervals(context.Context, *FindMissingCandlePeriodsRequest) (*FindMissingIntervalsResponse, error) + FindMissingSavedTradeIntervals(context.Context, *FindMissingTradePeriodsRequest) (*FindMissingIntervalsResponse, error) + SetExchangeTradeProcessing(context.Context, *SetExchangeTradeProcessingRequest) (*GenericResponse, error) } // UnimplementedGoCryptoTraderServer can be embedded to have forward compatible implementations. @@ -12982,6 +14007,27 @@ func (*UnimplementedGoCryptoTraderServer) WebsocketSetProxy(context.Context, *We func (*UnimplementedGoCryptoTraderServer) WebsocketSetURL(context.Context, *WebsocketSetURLRequest) (*GenericResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method WebsocketSetURL not implemented") } +func (*UnimplementedGoCryptoTraderServer) GetRecentTrades(context.Context, *GetSavedTradesRequest) (*SavedTradesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRecentTrades not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetHistoricTrades(*GetSavedTradesRequest, GoCryptoTrader_GetHistoricTradesServer) error { + return status.Errorf(codes.Unimplemented, "method GetHistoricTrades not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetSavedTrades(context.Context, *GetSavedTradesRequest) (*SavedTradesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSavedTrades not implemented") +} +func (*UnimplementedGoCryptoTraderServer) ConvertTradesToCandles(context.Context, *ConvertTradesToCandlesRequest) (*GetHistoricCandlesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ConvertTradesToCandles not implemented") +} +func (*UnimplementedGoCryptoTraderServer) FindMissingSavedCandleIntervals(context.Context, *FindMissingCandlePeriodsRequest) (*FindMissingIntervalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindMissingSavedCandleIntervals not implemented") +} +func (*UnimplementedGoCryptoTraderServer) FindMissingSavedTradeIntervals(context.Context, *FindMissingTradePeriodsRequest) (*FindMissingIntervalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FindMissingSavedTradeIntervals not implemented") +} +func (*UnimplementedGoCryptoTraderServer) SetExchangeTradeProcessing(context.Context, *SetExchangeTradeProcessingRequest) (*GenericResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetExchangeTradeProcessing not implemented") +} func RegisterGoCryptoTraderServer(s *grpc.Server, srv GoCryptoTraderServer) { s.RegisterService(&_GoCryptoTrader_serviceDesc, srv) @@ -14262,6 +15308,135 @@ func _GoCryptoTrader_WebsocketSetURL_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _GoCryptoTrader_GetRecentTrades_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSavedTradesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).GetRecentTrades(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/GetRecentTrades", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).GetRecentTrades(ctx, req.(*GetSavedTradesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GoCryptoTrader_GetHistoricTrades_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetSavedTradesRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GoCryptoTraderServer).GetHistoricTrades(m, &goCryptoTraderGetHistoricTradesServer{stream}) +} + +type GoCryptoTrader_GetHistoricTradesServer interface { + Send(*SavedTradesResponse) error + grpc.ServerStream +} + +type goCryptoTraderGetHistoricTradesServer struct { + grpc.ServerStream +} + +func (x *goCryptoTraderGetHistoricTradesServer) Send(m *SavedTradesResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GoCryptoTrader_GetSavedTrades_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSavedTradesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).GetSavedTrades(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/GetSavedTrades", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).GetSavedTrades(ctx, req.(*GetSavedTradesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GoCryptoTrader_ConvertTradesToCandles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConvertTradesToCandlesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).ConvertTradesToCandles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/ConvertTradesToCandles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).ConvertTradesToCandles(ctx, req.(*ConvertTradesToCandlesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GoCryptoTrader_FindMissingSavedCandleIntervals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindMissingCandlePeriodsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).FindMissingSavedCandleIntervals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).FindMissingSavedCandleIntervals(ctx, req.(*FindMissingCandlePeriodsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GoCryptoTrader_FindMissingSavedTradeIntervals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FindMissingTradePeriodsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).FindMissingSavedTradeIntervals(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).FindMissingSavedTradeIntervals(ctx, req.(*FindMissingTradePeriodsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GoCryptoTrader_SetExchangeTradeProcessing_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetExchangeTradeProcessingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GoCryptoTraderServer).SetExchangeTradeProcessing(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GoCryptoTraderServer).SetExchangeTradeProcessing(ctx, req.(*SetExchangeTradeProcessingRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{ ServiceName: "gctrpc.GoCryptoTrader", HandlerType: (*GoCryptoTraderServer)(nil), @@ -14526,6 +15701,30 @@ var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{ MethodName: "WebsocketSetURL", Handler: _GoCryptoTrader_WebsocketSetURL_Handler, }, + { + MethodName: "GetRecentTrades", + Handler: _GoCryptoTrader_GetRecentTrades_Handler, + }, + { + MethodName: "GetSavedTrades", + Handler: _GoCryptoTrader_GetSavedTrades_Handler, + }, + { + MethodName: "ConvertTradesToCandles", + Handler: _GoCryptoTrader_ConvertTradesToCandles_Handler, + }, + { + MethodName: "FindMissingSavedCandleIntervals", + Handler: _GoCryptoTrader_FindMissingSavedCandleIntervals_Handler, + }, + { + MethodName: "FindMissingSavedTradeIntervals", + Handler: _GoCryptoTrader_FindMissingSavedTradeIntervals_Handler, + }, + { + MethodName: "SetExchangeTradeProcessing", + Handler: _GoCryptoTrader_SetExchangeTradeProcessing_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -14553,6 +15752,11 @@ var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{ Handler: _GoCryptoTrader_GetExchangeTickerStream_Handler, ServerStreams: true, }, + { + StreamName: "GetHistoricTrades", + Handler: _GoCryptoTrader_GetHistoricTrades_Handler, + ServerStreams: true, + }, }, Metadata: "rpc.proto", } diff --git a/gctrpc/rpc.pb.gw.go b/gctrpc/rpc.pb.gw.go index 6db69625..459b13a9 100644 --- a/gctrpc/rpc.pb.gw.go +++ b/gctrpc/rpc.pb.gw.go @@ -91,10 +91,7 @@ func local_request_GoCryptoTrader_EnableSubsystem_0(ctx context.Context, marshal var protoReq GenericSubsystemRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_EnableSubsystem_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_EnableSubsystem_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -127,10 +124,7 @@ func local_request_GoCryptoTrader_DisableSubsystem_0(ctx context.Context, marsha var protoReq GenericSubsystemRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_DisableSubsystem_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_DisableSubsystem_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -199,10 +193,7 @@ func local_request_GoCryptoTrader_GetExchanges_0(ctx context.Context, marshaler var protoReq GetExchangesRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchanges_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchanges_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -269,10 +260,7 @@ func local_request_GoCryptoTrader_GetExchangeInfo_0(ctx context.Context, marshal var protoReq GenericExchangeNameRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeInfo_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeInfo_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -305,10 +293,7 @@ func local_request_GoCryptoTrader_GetExchangeOTPCode_0(ctx context.Context, mars var protoReq GenericExchangeNameRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeOTPCode_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeOTPCode_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -497,10 +482,7 @@ func local_request_GoCryptoTrader_GetAccountInfo_0(ctx context.Context, marshale var protoReq GetAccountInfoRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetAccountInfo_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAccountInfo_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1281,10 +1263,7 @@ func local_request_GoCryptoTrader_GetLoggerDetails_0(ctx context.Context, marsha var protoReq GetLoggerDetailsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetLoggerDetails_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetLoggerDetails_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1531,10 +1510,7 @@ func local_request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler var protoReq GetAuditEventRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetAuditEvent_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAuditEvent_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1567,10 +1543,7 @@ func local_request_GoCryptoTrader_GCTScriptExecute_0(ctx context.Context, marsha var protoReq GCTScriptExecuteRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptExecute_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptExecute_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1689,10 +1662,7 @@ func local_request_GoCryptoTrader_GCTScriptQuery_0(ctx context.Context, marshale var protoReq GCTScriptQueryRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptQuery_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptQuery_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1861,10 +1831,7 @@ func local_request_GoCryptoTrader_GetHistoricCandles_0(ctx context.Context, mars var protoReq GetHistoricCandlesRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetHistoricCandles_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetHistoricCandles_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1897,10 +1864,7 @@ func local_request_GoCryptoTrader_SetExchangeAsset_0(ctx context.Context, marsha var protoReq SetExchangeAssetRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_SetExchangeAsset_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_SetExchangeAsset_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1933,10 +1897,7 @@ func local_request_GoCryptoTrader_SetAllExchangePairs_0(ctx context.Context, mar var protoReq SetExchangeAllPairsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_SetAllExchangePairs_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_SetAllExchangePairs_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -1969,10 +1930,7 @@ func local_request_GoCryptoTrader_UpdateExchangeSupportedPairs_0(ctx context.Con var protoReq UpdateExchangeSupportedPairsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_UpdateExchangeSupportedPairs_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_UpdateExchangeSupportedPairs_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2005,10 +1963,7 @@ func local_request_GoCryptoTrader_GetExchangeAssets_0(ctx context.Context, marsh var protoReq GetExchangeAssetsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeAssets_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeAssets_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2041,10 +1996,7 @@ func local_request_GoCryptoTrader_WebsocketGetInfo_0(ctx context.Context, marsha var protoReq WebsocketGetInfoRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketGetInfo_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketGetInfo_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2077,10 +2029,7 @@ func local_request_GoCryptoTrader_WebsocketSetEnabled_0(ctx context.Context, mar var protoReq WebsocketSetEnabledRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetEnabled_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetEnabled_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2113,10 +2062,7 @@ func local_request_GoCryptoTrader_WebsocketGetSubscriptions_0(ctx context.Contex var protoReq WebsocketGetSubscriptionsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketGetSubscriptions_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketGetSubscriptions_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2149,10 +2095,7 @@ func local_request_GoCryptoTrader_WebsocketSetProxy_0(ctx context.Context, marsh var protoReq WebsocketSetProxyRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetProxy_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetProxy_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2185,10 +2128,7 @@ func local_request_GoCryptoTrader_WebsocketSetURL_0(ctx context.Context, marshal var protoReq WebsocketSetURLRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetURL_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetURL_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -2197,6 +2137,232 @@ func local_request_GoCryptoTrader_WebsocketSetURL_0(ctx context.Context, marshal } +var ( + filter_GoCryptoTrader_GetRecentTrades_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetRecentTrades_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSavedTradesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetRecentTrades_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetRecentTrades(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetRecentTrades_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSavedTradesRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetRecentTrades_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetRecentTrades(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_GetHistoricTrades_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetHistoricTrades_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetHistoricTradesClient, runtime.ServerMetadata, error) { + var protoReq GetSavedTradesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetHistoricTrades_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetHistoricTrades(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +var ( + filter_GoCryptoTrader_GetSavedTrades_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetSavedTrades_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSavedTradesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetSavedTrades_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetSavedTrades(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetSavedTrades_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSavedTradesRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetSavedTrades_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetSavedTrades(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_ConvertTradesToCandles_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_ConvertTradesToCandles_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ConvertTradesToCandlesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_ConvertTradesToCandles_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ConvertTradesToCandles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_ConvertTradesToCandles_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ConvertTradesToCandlesRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_ConvertTradesToCandles_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ConvertTradesToCandles(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_FindMissingSavedCandleIntervals_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_FindMissingSavedCandleIntervals_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq FindMissingCandlePeriodsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_FindMissingSavedCandleIntervals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.FindMissingSavedCandleIntervals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_FindMissingSavedCandleIntervals_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq FindMissingCandlePeriodsRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_FindMissingSavedCandleIntervals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.FindMissingSavedCandleIntervals(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_FindMissingSavedTradeIntervals_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_FindMissingSavedTradeIntervals_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq FindMissingTradePeriodsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_FindMissingSavedTradeIntervals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.FindMissingSavedTradeIntervals(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_FindMissingSavedTradeIntervals_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq FindMissingTradePeriodsRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_FindMissingSavedTradeIntervals_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.FindMissingSavedTradeIntervals(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_SetExchangeTradeProcessing_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_SetExchangeTradeProcessing_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetExchangeTradeProcessingRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_SetExchangeTradeProcessing_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.SetExchangeTradeProcessing(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_SetExchangeTradeProcessing_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetExchangeTradeProcessingRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_SetExchangeTradeProcessing_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.SetExchangeTradeProcessing(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterGoCryptoTraderHandlerServer registers the http handlers for service GoCryptoTrader to "mux". // UnaryRPC :call GoCryptoTraderServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -3537,6 +3703,133 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve }) + mux.Handle("GET", pattern_GoCryptoTrader_GetRecentTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_GetRecentTrades_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_GetRecentTrades_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetHistoricTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetSavedTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_GetSavedTrades_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_GetSavedTrades_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_ConvertTradesToCandles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_ConvertTradesToCandles_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_ConvertTradesToCandles_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_FindMissingSavedCandleIntervals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_FindMissingSavedCandleIntervals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_FindMissingSavedCandleIntervals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_FindMissingSavedTradeIntervals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_FindMissingSavedTradeIntervals_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_FindMissingSavedTradeIntervals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_SetExchangeTradeProcessing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_GoCryptoTrader_SetExchangeTradeProcessing_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_SetExchangeTradeProcessing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -4978,6 +5271,146 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve }) + mux.Handle("GET", pattern_GoCryptoTrader_GetRecentTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_GetRecentTrades_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_GetRecentTrades_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetHistoricTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_GetHistoricTrades_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_GetHistoricTrades_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetSavedTrades_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_GetSavedTrades_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_GetSavedTrades_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_ConvertTradesToCandles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_ConvertTradesToCandles_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_ConvertTradesToCandles_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_FindMissingSavedCandleIntervals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_FindMissingSavedCandleIntervals_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_FindMissingSavedCandleIntervals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_FindMissingSavedTradeIntervals_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_FindMissingSavedTradeIntervals_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_FindMissingSavedTradeIntervals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_SetExchangeTradeProcessing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_GoCryptoTrader_SetExchangeTradeProcessing_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_GoCryptoTrader_SetExchangeTradeProcessing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -5121,6 +5554,20 @@ var ( pattern_GoCryptoTrader_WebsocketSetProxy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketsetproxy"}, "", runtime.AssumeColonVerbOpt(true))) pattern_GoCryptoTrader_WebsocketSetURL_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketseturl"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_GetRecentTrades_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getsavedtrades"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_GetHistoricTrades_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getsavedtrades"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_GetSavedTrades_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getsavedtrades"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_ConvertTradesToCandles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "converttradestocandles"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_FindMissingSavedCandleIntervals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "findmissingsavedcandleintervals"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_FindMissingSavedTradeIntervals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "findmissingsavedtradeintervals"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_GoCryptoTrader_SetExchangeTradeProcessing_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "setexchangetradeprocessing"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -5263,4 +5710,18 @@ var ( forward_GoCryptoTrader_WebsocketSetProxy_0 = runtime.ForwardResponseMessage forward_GoCryptoTrader_WebsocketSetURL_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_GetRecentTrades_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_GetHistoricTrades_0 = runtime.ForwardResponseStream + + forward_GoCryptoTrader_GetSavedTrades_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_ConvertTradesToCandles_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_FindMissingSavedCandleIntervals_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_FindMissingSavedTradeIntervals_0 = runtime.ForwardResponseMessage + + forward_GoCryptoTrader_SetExchangeTradeProcessing_0 = runtime.ForwardResponseMessage ) diff --git a/gctrpc/rpc.proto b/gctrpc/rpc.proto index 7c4bd77c..d3fe099f 100644 --- a/gctrpc/rpc.proto +++ b/gctrpc/rpc.proto @@ -1,1217 +1,1325 @@ -syntax = "proto3"; - -import "google/api/annotations.proto"; -import "google/protobuf/timestamp.proto"; - -package gctrpc; - -message GetInfoRequest {} - -message GetInfoResponse { - string uptime = 1; - int64 available_exchanges = 2; - int64 enabled_exchanges = 3; - string default_forex_provider = 4; - string default_fiat_currency = 5; - map subsystem_status = 6; - map rpc_endpoints = 7; -} - -message GetCommunicationRelayersRequest {} - -message CommunicationRelayer { - bool enabled = 1; - bool connected = 2; -} - -message GetCommunicationRelayersResponse { - map communication_relayers = 1; -} - -message GenericSubsystemRequest { - string subsystem = 1; -} - -message GetSubsystemsRequest {} - -message GetSusbsytemsResponse { - map subsystems_status = 1; -} - -message GetRPCEndpointsRequest{} - -message RPCEndpoint { - bool started = 1; - string listen_address = 2; -} - -message GetRPCEndpointsResponse { - map endpoints = 1; -} - -message GenericExchangeNameRequest { - string exchange = 1; -} - -message GetExchangesRequest { - bool enabled = 1; -} - -message GetExchangesResponse { - string exchanges = 1; -} - -message GetExchangeOTPReponse { - string otp_code = 1; -} - -message GetExchangeOTPsRequest {} - -message GetExchangeOTPsResponse { - map otp_codes = 1; -} - -message DisableExchangeRequest { - string exchange = 1; -} - -message PairsSupported { - string available_pairs = 1; - string enabled_pairs = 2; -} - -message GetExchangeInfoResponse { - string name = 1; - bool enabled = 2; - bool verbose = 3; - bool using_sandbox = 4; - string http_timeout = 5; - string http_useragent = 6; - string http_proxy = 7; - string base_currencies = 8; - map supported_assets = 9; - bool authenticated_api = 10; -} - -message GetTickerRequest { - string exchange = 1; - CurrencyPair pair = 2; - string asset_type = 3; -} - -message CurrencyPair { - string delimiter = 1; - string base = 2; - string quote = 3; -} - -message TickerResponse { - CurrencyPair pair = 1; - int64 last_updated = 2; - string currency_pair = 3; - double last = 4; - double high = 5; - double low = 6; - double bid = 7; - double ask = 8; - double volume = 9; - double price_ath = 10; -} - -message GetTickersRequest {} - -message Tickers { - string exchange = 1; - repeated TickerResponse tickers = 2; -} - -message GetTickersResponse { - repeated Tickers tickers = 1; -} - -message GetOrderbookRequest { - string exchange = 1; - CurrencyPair pair = 2; - string asset_type = 3; -} - -message OrderbookItem { - double amount = 1; - double price = 2; - int64 id = 3; -} - -message OrderbookResponse { - CurrencyPair pair = 1; - string currency_pair = 2; - repeated OrderbookItem bids = 3; - repeated OrderbookItem asks = 4; - int64 last_updated = 5; - string asset_type = 6; -} - -message GetOrderbooksRequest {} - -message Orderbooks { - string exchange = 1; - repeated OrderbookResponse orderbooks = 2; -} - -message GetOrderbooksResponse { - repeated Orderbooks orderbooks = 1; -} - -message GetAccountInfoRequest { - string exchange = 1; -} - -message Account { - string id = 1; - repeated AccountCurrencyInfo currencies = 2; -} - -message AccountCurrencyInfo { - string currency = 1; - double total_value = 2; - double hold = 3; -} - -message GetAccountInfoResponse { - string exchange = 1; - repeated Account accounts = 2; -} - -message GetConfigRequest {} - -message GetConfigResponse { - bytes data = 1; -} - -message PortfolioAddress { - string address = 1; - string coin_type = 2; - string description = 3; - double balance = 4; -} - -message GetPortfolioRequest {} - -message GetPortfolioResponse { - repeated PortfolioAddress portfolio = 1; -} - -message GetPortfolioSummaryRequest {} - -message Coin { - string coin = 1; - double balance = 2; - string address = 3; - double percentage = 4; -} - -message OfflineCoinSummary { - string address = 1; - double balance = 2; - double percentage = 3; -} - -message OnlineCoinSummary { - double balance = 1; - double percentage = 2; -} - -message OfflineCoins { - repeated OfflineCoinSummary addresses = 1; -} - -message OnlineCoins { - map coins = 1; -} - -message GetPortfolioSummaryResponse { - repeated Coin coin_totals = 1; - repeated Coin coins_offline = 2; - map coins_offline_summary = 3; - repeated Coin coins_online = 4; - map coins_online_summary = 5; -} - -message AddPortfolioAddressRequest { - string address = 1; - string coin_type = 2; - string description = 3; - double balance = 4; - string supported_exchanges = 5; - bool cold_storage = 6; -} - -message RemovePortfolioAddressRequest { - string address = 1; - string coin_type = 2; - string description = 3; -} - -message GetForexProvidersRequest {} - -message ForexProvider { - string name = 1; - bool enabled = 2; - bool verbose = 3; - string rest_polling_delay = 4; - string api_key = 5; - int64 api_key_level =6; - bool primary_provider = 7; -} - -message GetForexProvidersResponse { - repeated ForexProvider forex_providers = 1; -} - -message GetForexRatesRequest {} - -message ForexRatesConversion { - string from = 1; - string to = 2; - double rate = 3; - double inverse_rate = 4; - -} -message GetForexRatesResponse { - repeated ForexRatesConversion forex_rates = 1; -} - -message OrderDetails { - string exchange = 1; - string id = 2; - string client_order_id = 3; - string base_currency = 4; - string quote_currency = 5; - string asset_type = 6; - string order_side = 7; - string order_type = 8; - int64 creation_time = 9; - int64 update_time = 10; - string status = 11; - double price = 12; - double amount = 13; - double open_volume = 14; - double fee = 15; - double cost = 16; - repeated TradeHistory trades = 17; -} - -message TradeHistory { - int64 creation_time = 1; - string id = 2; - double price = 3; - double amount = 4; - string exchange = 5; - string asset_type = 6; - string order_side = 7; - double fee = 8; -} - -message GetOrdersRequest { - string exchange = 1; - string asset_type = 2; - CurrencyPair pair = 3; -} - -message GetOrdersResponse { - repeated OrderDetails orders = 1; -} - -message GetOrderRequest { - string exchange = 1; - string order_id = 2; - CurrencyPair pair = 3; -} - -message SubmitOrderRequest { - string exchange = 1; - CurrencyPair pair = 2; - string side = 3; - string order_type = 4; - double amount = 5; - double price = 6; - string client_id = 7; - string asset_type = 8; -} - -message Trades { - double amount = 1; - double price = 2; - double fee = 3; - string fee_asset = 4; -} - -message SubmitOrderResponse { - bool order_placed = 1; - string order_id = 2; - repeated Trades trades= 3; -} - -message SimulateOrderRequest { - string exchange = 1; - CurrencyPair pair = 2; - double amount = 3; - string side = 4; -} - -message SimulateOrderResponse { - repeated OrderbookItem orders = 1; - double amount = 2; - double minimum_price = 3; - double maximum_price = 4; - double percentage_gain_loss = 5; - string status = 6; -} - -message WhaleBombRequest { - string exchange = 1; - CurrencyPair pair = 2; - double price_target = 3; - string side = 4; -} - -message CancelOrderRequest { - string exchange = 1; - string account_id = 2; - string order_id = 3; - CurrencyPair pair = 4; - string asset_type = 5; - string wallet_address = 6; - string side = 7; -} - -message CancelAllOrdersRequest { - string exchange = 1; -} - -message CancelAllOrdersResponse { - message Orders { - string exchange = 1; - map order_status = 2; - } - repeated Orders orders = 1; -} - -message GetEventsRequest {} - - -message ConditionParams { - string condition = 1; - double price = 2; - bool check_bids = 3; - bool check_bids_and_asks = 4; - double orderbook_amount = 5; -} - -message GetEventsResponse { - int64 id = 1; - string exchange = 2; - string item = 3; - ConditionParams condition_params = 4; - CurrencyPair pair = 5; - string action = 6; - bool executed = 7; -} - -message AddEventRequest { - string exchange = 1; - string item = 2; - ConditionParams condition_params = 3; - CurrencyPair pair = 4; - string asset_type = 5; - string action = 6; -} - -message AddEventResponse { - int64 id = 1; -} - -message RemoveEventRequest { - int64 id = 1; -} - -message GetCryptocurrencyDepositAddressesRequest { - string exchange = 1; -} - -message GetCryptocurrencyDepositAddressesResponse { - map addresses = 1; -} - -message GetCryptocurrencyDepositAddressRequest { - string exchange = 1; - string cryptocurrency = 2; -} - -message GetCryptocurrencyDepositAddressResponse { - string address = 1; -} - -message WithdrawFiatRequest { - string exchange = 1; - string currency = 2; - double amount = 3; - string description = 4; - string bank_account_id = 5; -} - -message WithdrawCryptoRequest { - string exchange = 1; - string address = 2; - string address_tag = 3; - string currency = 4; - double amount = 5; - double fee = 6; - string description = 7; -} - -message WithdrawResponse { - string id = 1; - string status = 2; -} - -message WithdrawalEventByIDRequest { - string id = 1; -} - -message WithdrawalEventByIDResponse { - WithdrawalEventResponse event = 2; -} - -message WithdrawalEventsByExchangeRequest { - string exchange = 1; - string id = 2; - int32 limit = 3; -} - -message WithdrawalEventsByDateRequest { - string exchange = 1; - string start = 2; - string end = 3; - int32 limit = 4; -} - -message WithdrawalEventsByExchangeResponse { - repeated WithdrawalEventResponse event = 2; -} - -message WithdrawalEventResponse { - string id = 2; - WithdrawlExchangeEvent exchange = 3; - WithdrawalRequestEvent request = 4; - google.protobuf.Timestamp created_at = 5; - google.protobuf.Timestamp updated_at = 6; -} - -message WithdrawlExchangeEvent { - string name = 1; - string id = 2; - string status = 3; -} - -message WithdrawalRequestEvent { - string currency = 2; - string description = 3; - double amount = 4; - int32 type = 5; - FiatWithdrawalEvent fiat = 6; - CryptoWithdrawalEvent crypto = 7; -} - -message FiatWithdrawalEvent { - string bank_name = 1; - string account_name = 2; - string account_number = 3; - string bsb = 4; - string swift = 5; - string iban = 6; -} - -message CryptoWithdrawalEvent { - string address = 1; - string address_tag = 2; - double fee = 3; -} - -message GetLoggerDetailsRequest { - string logger = 1; -} - -message GetLoggerDetailsResponse{ - bool info = 1; - bool debug = 2; - bool warn = 3; - bool error = 4; -} - -message SetLoggerDetailsRequest { - string logger = 1; - string level = 2; -} - -message GetExchangePairsRequest { - string exchange = 1; - string asset = 2; -} - -message GetExchangePairsResponse { - map supported_assets = 1; -} - -message SetExchangePairRequest { - string exchange = 1; - string asset_type = 2; - repeated CurrencyPair pairs = 3; - bool enable = 4; -} - -message GetOrderbookStreamRequest { - string exchange = 1; - CurrencyPair pair = 2; - string asset_type = 3; -} - -message GetExchangeOrderbookStreamRequest { - string exchange = 1; -} - -message GetTickerStreamRequest { - string exchange = 1; - CurrencyPair pair = 2; - string asset_type = 3; -} - -message GetExchangeTickerStreamRequest { - string exchange = 1; -} - -message GetAuditEventRequest { - string start_date = 1; - string end_date = 2; - string order_by = 3; - int32 limit = 4; - int32 offset = 5; -} - -message GetAuditEventResponse { - repeated AuditEvent events = 1; -} - -message GetHistoricCandlesRequest { - string exchange = 1; - CurrencyPair pair = 2; - string asset_type = 3; - int64 start = 4; - int64 end = 5; - int64 time_interval = 6; - bool ex_request = 7; - bool sync = 8; - bool use_db = 9; -} - -message GetHistoricCandlesResponse { - string exchange = 1; - CurrencyPair pair = 2; - int64 start = 3; - int64 end = 4; - string interval = 6; - repeated Candle candle = 5; -} - -message Candle { - int64 time = 1; - double low = 2; - double high = 3; - double open = 4; - double close = 5; - double volume = 6; -} - -message AuditEvent { - string type = 1; - string identifier = 2; - string message = 3; - string timestamp = 4; -} - -message GCTScript { - string UUID = 1; - string name = 2; - string path = 3; - string next_run = 4; -} - -message GCTScriptExecuteRequest { - GCTScript script = 1; -} - -message GCTScriptStopRequest { - GCTScript script = 1; -} - -message GCTScriptStopAllRequest{} -message GCTScriptStatusRequest {} -message GCTScriptListAllRequest{} - -message GCTScriptUploadRequest { - string script_name = 1; - string script_data = 2; - bytes data = 3; - bool archived = 4; - bool overwrite = 5; -} - -message GCTScriptReadScriptRequest{ - GCTScript script = 1; -} - -message GCTScriptQueryRequest{ - GCTScript script = 1; -} - -message GCTScriptAutoLoadRequest{ - string script = 1; - bool status = 2; -} - -message GCTScriptStatusResponse{ - string status = 1; - repeated GCTScript scripts = 2; -} - -message GCTScriptQueryResponse{ - string status = 1; - GCTScript script = 2; - string data = 3; -} - -message GenericResponse { - string status = 1; - string data = 2; -} - -message SetExchangeAssetRequest { - string exchange = 1; - string asset = 2; - bool enable = 3; -} - -message SetExchangeAllPairsRequest { - string exchange = 1; - bool enable = 2; -} - -message UpdateExchangeSupportedPairsRequest { - string exchange = 1; -} - -message GetExchangeAssetsRequest { - string exchange = 1; -} - -message GetExchangeAssetsResponse { - string assets = 1; -} - -message WebsocketGetInfoRequest { - string exchange = 1; -} - -message WebsocketGetInfoResponse { - string exchange = 1; - bool supported = 2; - bool enabled = 3; - bool authenticated_supported = 4; - bool authenticated = 5; - string running_url = 6; - string proxy_address = 7; -} - -message WebsocketSetEnabledRequest { - string exchange = 1; - bool enable = 2; -} - -message WebsocketGetSubscriptionsRequest { - string exchange = 1; -} - -message WebsocketSubscription { - string channel = 1; - string currency = 2; - string asset = 3; - string params = 4; -} - -message WebsocketGetSubscriptionsResponse { - string exchange = 1; - repeated WebsocketSubscription subscriptions = 2; -} - -message WebsocketSetProxyRequest { - string exchange = 1; - string proxy = 2; -} - -message WebsocketSetURLRequest { - string exchange = 1; - string url = 2; -} - -service GoCryptoTrader { - rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) { - option (google.api.http) = { - get :"/v1/getinfo" - }; - } - - rpc GetSubsystems (GetSubsystemsRequest) returns (GetSusbsytemsResponse) { - option (google.api.http) = { - get: "/v1/getsubsystems" - }; - } - - rpc EnableSubsystem (GenericSubsystemRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/enablesubsystem" - }; - } - - rpc DisableSubsystem (GenericSubsystemRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/disablesubsystem" - }; - } - - rpc GetRPCEndpoints (GetRPCEndpointsRequest) returns (GetRPCEndpointsResponse) { - option (google.api.http) = { - get: "/v1/getrpcendpoints" - }; - } - - rpc GetCommunicationRelayers (GetCommunicationRelayersRequest) returns (GetCommunicationRelayersResponse) { - option (google.api.http) = { - get: "/v1/getcommunicationrelayers" - }; - } - - rpc GetExchanges (GetExchangesRequest) returns (GetExchangesResponse) { - option (google.api.http) = { - get: "/v1/getexchanges" - }; - } - - rpc DisableExchange (GenericExchangeNameRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/disableexchange" - body: "*" - }; - } - - rpc GetExchangeInfo (GenericExchangeNameRequest) returns (GetExchangeInfoResponse) { - option (google.api.http) = { - get: "/v1/getexchangeinfo" - }; - } - - rpc GetExchangeOTPCode (GenericExchangeNameRequest) returns (GetExchangeOTPReponse) { - option (google.api.http) = { - get: "/v1/getexchangeotp" - }; - } - - rpc GetExchangeOTPCodes (GetExchangeOTPsRequest) returns (GetExchangeOTPsResponse) { - option (google.api.http) = { - get: "/v1/getexchangeotps" - }; - } - - rpc EnableExchange (GenericExchangeNameRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/enableexchange" - body: "*" - }; - } - - rpc GetTicker (GetTickerRequest) returns (TickerResponse) { - option (google.api.http) = { - post: "/v1/getticker" - body: "*" - }; - } - - rpc GetTickers (GetTickersRequest) returns (GetTickersResponse) { - option (google.api.http) = { - get: "/v1/gettickers" - }; - } - - rpc GetOrderbook (GetOrderbookRequest) returns (OrderbookResponse) { - option (google.api.http) = { - post: "/v1/getorderbook" - body: "*" - }; - } - - rpc GetOrderbooks (GetOrderbooksRequest) returns (GetOrderbooksResponse) { - option (google.api.http) = { - get: "/v1/getorderbooks" - }; - } - - rpc GetAccountInfo (GetAccountInfoRequest) returns (GetAccountInfoResponse) { - option (google.api.http) = { - get: "/v1/getaccountinfo" - }; - } - - rpc GetAccountInfoStream (GetAccountInfoRequest) returns (stream GetAccountInfoResponse) { - option (google.api.http) = { - get: "/v1/getaccountinfostream" - }; - } - - rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) { - option (google.api.http) = { - get: "/v1/getconfig" - }; - } - - rpc GetPortfolio (GetPortfolioRequest) returns (GetPortfolioResponse) { - option (google.api.http) = { - get: "/v1/getportfolio" - }; - } - - rpc GetPortfolioSummary (GetPortfolioSummaryRequest) returns (GetPortfolioSummaryResponse) { - option (google.api.http) = { - get: "/v1/getportfoliosummary" - }; - } - - - rpc AddPortfolioAddress (AddPortfolioAddressRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/addportfolioaddress" - body: "*" - }; - } - - rpc RemovePortfolioAddress (RemovePortfolioAddressRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/removeportfolioaddress" - body: "*" - }; - } - - rpc GetForexProviders (GetForexProvidersRequest) returns (GetForexProvidersResponse) { - option (google.api.http) = { - get: "/v1/getforexproviders" - }; - } - - rpc GetForexRates (GetForexRatesRequest) returns (GetForexRatesResponse) { - option (google.api.http) = { - get: "/v1/getforexrates" - }; - } - - rpc GetOrders (GetOrdersRequest) returns (GetOrdersResponse) { - option (google.api.http) = { - post: "/v1/getorders" - body: "*" - }; - } - - rpc GetOrder (GetOrderRequest) returns (OrderDetails) { - option (google.api.http) = { - post: "/v1/getorder" - body: "*" - }; - } - - rpc SubmitOrder (SubmitOrderRequest) returns (SubmitOrderResponse) { - option (google.api.http) = { - post: "/v1/submitorder" - body: "*" - }; - } - - rpc SimulateOrder (SimulateOrderRequest) returns (SimulateOrderResponse) { - option (google.api.http) = { - post: "/v1/simulateorder" - body: "*" - }; - } - - rpc WhaleBomb (WhaleBombRequest) returns (SimulateOrderResponse) { - option (google.api.http) = { - post: "/v1/whalebomb" - body: "*" - }; - } - - rpc CancelOrder (CancelOrderRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/cancelorder" - body: "*" - }; - } - - rpc CancelAllOrders (CancelAllOrdersRequest) returns (CancelAllOrdersResponse) { - option (google.api.http) = { - post: "/v1/cancelallorders" - body: "*" - }; - } - - rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) { - option (google.api.http) = { - get: "/v1/getevents" - }; - } - - rpc AddEvent(AddEventRequest) returns (AddEventResponse) { - option (google.api.http) = { - post: "/v1/addevent" - body: "*" - }; - } - - rpc RemoveEvent(RemoveEventRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/removeevent" - body: "*" - }; - } - - rpc GetCryptocurrencyDepositAddresses(GetCryptocurrencyDepositAddressesRequest) returns (GetCryptocurrencyDepositAddressesResponse) { - option (google.api.http) = { - post: "/v1/getcryptodepositaddresses" - body: "*" - }; - } - - rpc GetCryptocurrencyDepositAddress(GetCryptocurrencyDepositAddressRequest) returns (GetCryptocurrencyDepositAddressResponse) { - option (google.api.http) = { - post: "/v1/getcryptodepositaddress" - body: "*" - }; - } - - - rpc WithdrawFiatFunds(WithdrawFiatRequest) returns (WithdrawResponse) { - option (google.api.http) = { - post: "/v1/withdrawfiatfunds" - body: "*" - }; - } - - rpc WithdrawCryptocurrencyFunds(WithdrawCryptoRequest) returns (WithdrawResponse) { - option (google.api.http) = { - post: "/v1/withdrawithdrawcryptofundswfiatfunds" - body: "*" - }; - } - - rpc WithdrawalEventByID(WithdrawalEventByIDRequest) returns (WithdrawalEventByIDResponse) { - option (google.api.http) = { - post: "/v1/withdrawaleventbyid" - body: "*" - }; - } - - rpc WithdrawalEventsByExchange(WithdrawalEventsByExchangeRequest) returns (WithdrawalEventsByExchangeResponse) { - option (google.api.http) = { - post: "/v1/withdrawaleventbyid" - body: "*" - }; - } - - rpc WithdrawalEventsByDate(WithdrawalEventsByDateRequest) returns (WithdrawalEventsByExchangeResponse) { - option (google.api.http) = { - post: "/v1/withdrawaleventbydate" - body: "*" - }; - } - - rpc GetLoggerDetails(GetLoggerDetailsRequest) returns (GetLoggerDetailsResponse) { - option (google.api.http) = { - get: "/v1/getloggerdetails" - }; - } - - rpc SetLoggerDetails(SetLoggerDetailsRequest) returns (GetLoggerDetailsResponse) { - option (google.api.http) = { - post: "/v1/setloggerdetails", - body: "*" - }; - } - - rpc GetExchangePairs(GetExchangePairsRequest) returns (GetExchangePairsResponse) { - option (google.api.http) = { - post: "/v1/getexchangepairs", - body: "*" - }; - } - - rpc SetExchangePair(SetExchangePairRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/setexchangepair", - body: "*" - }; - } - - rpc GetOrderbookStream(GetOrderbookStreamRequest) returns (stream OrderbookResponse) { - option (google.api.http) = { - get: "/v1/getorderbookstream" - }; - } - - rpc GetExchangeOrderbookStream(GetExchangeOrderbookStreamRequest) returns (stream OrderbookResponse) { - option (google.api.http) = { - get: "/v1/getexchangeorderbookstream" - }; - } - - rpc GetTickerStream(GetTickerStreamRequest) returns (stream TickerResponse) { - option (google.api.http) = { - get: "/v1/gettickerstream" - }; - } - - rpc GetExchangeTickerStream(GetExchangeTickerStreamRequest) returns (stream TickerResponse) { - option (google.api.http) = { - get: "/v1/getexchangetickerstream", - }; - } - - rpc GetAuditEvent(GetAuditEventRequest) returns (GetAuditEventResponse) { - option (google.api.http) = { - get: "/v1/getauditevent", - }; - } - - rpc GCTScriptExecute(GCTScriptExecuteRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/gctscript/execute", - }; - } - - rpc GCTScriptUpload(GCTScriptUploadRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/gctscript/upload", - body: "*" - }; - } - - rpc GCTScriptReadScript(GCTScriptReadScriptRequest) returns (GCTScriptQueryResponse) { - option (google.api.http) = { - post: "/v1/gctscript/read", - body: "*" - }; - } - - rpc GCTScriptStatus(GCTScriptStatusRequest) returns (GCTScriptStatusResponse) { - option (google.api.http) = { - get: "/v1/gctscript/status", - }; - } - - rpc GCTScriptQuery(GCTScriptQueryRequest) returns (GCTScriptQueryResponse) { - option (google.api.http) = { - get: "/v1/gctscript/query", - }; - } - - rpc GCTScriptStop(GCTScriptStopRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/gctscript/stop", - body: "*" - }; - } - - rpc GCTScriptStopAll(GCTScriptStopAllRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/gctscript/stop", - body: "*" - }; - } - - rpc GCTScriptListAll(GCTScriptListAllRequest) returns (GCTScriptStatusResponse) { - option (google.api.http) = { - post: "/v1/gctscript/stop", - body: "*" - }; - } - rpc GCTScriptAutoLoadToggle(GCTScriptAutoLoadRequest) returns (GenericResponse) { - option (google.api.http) = { - post: "/v1/gctscript/autoload", - body: "*" - }; - } - - rpc GetHistoricCandles(GetHistoricCandlesRequest) returns (GetHistoricCandlesResponse) { - option (google.api.http) = { - get: "/v1/gethistoriccandles" - }; - } - - rpc SetExchangeAsset(SetExchangeAssetRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/setexchangeasset" - }; - } - - rpc SetAllExchangePairs(SetExchangeAllPairsRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/setallexchangepairs" - }; - } - - rpc UpdateExchangeSupportedPairs(UpdateExchangeSupportedPairsRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/updateexchangesupportedpairs" - }; - } - - rpc GetExchangeAssets(GetExchangeAssetsRequest) returns (GetExchangeAssetsResponse) { - option (google.api.http) = { - get: "/v1/getexchangeassets" - }; - } - - rpc WebsocketGetInfo(WebsocketGetInfoRequest) returns (WebsocketGetInfoResponse) { - option (google.api.http) = { - get: "/v1/websocketgetinfo" - }; - } - - rpc WebsocketSetEnabled(WebsocketSetEnabledRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/websocketsetenabled" - }; - } - - rpc WebsocketGetSubscriptions(WebsocketGetSubscriptionsRequest) returns (WebsocketGetSubscriptionsResponse) { - option (google.api.http) = { - get: "/v1/websocketgetsubscriptions" - }; - } - - rpc WebsocketSetProxy(WebsocketSetProxyRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/websocketsetproxy" - }; - } - - rpc WebsocketSetURL(WebsocketSetURLRequest) returns (GenericResponse) { - option (google.api.http) = { - get: "/v1/websocketseturl" - }; - } +syntax = "proto3"; +import "google/api/annotations.proto"; +import "google/protobuf/timestamp.proto"; + +package gctrpc; +option go_package = ".;gctrpc"; + +message GetInfoRequest {} + +message GetInfoResponse { + string uptime = 1; + int64 available_exchanges = 2; + int64 enabled_exchanges = 3; + string default_forex_provider = 4; + string default_fiat_currency = 5; + map subsystem_status = 6; + map rpc_endpoints = 7; +} + +message GetCommunicationRelayersRequest {} + +message CommunicationRelayer { + bool enabled = 1; + bool connected = 2; +} + +message GetCommunicationRelayersResponse { + map communication_relayers = 1; +} + +message GenericSubsystemRequest { + string subsystem = 1; +} + +message GetSubsystemsRequest {} + +message GetSusbsytemsResponse { + map subsystems_status = 1; +} + +message GetRPCEndpointsRequest{} + +message RPCEndpoint { + bool started = 1; + string listen_address = 2; +} + +message GetRPCEndpointsResponse { + map endpoints = 1; +} + +message GenericExchangeNameRequest { + string exchange = 1; +} + +message GetExchangesRequest { + bool enabled = 1; +} + +message GetExchangesResponse { + string exchanges = 1; +} + +message GetExchangeOTPReponse { + string otp_code = 1; +} + +message GetExchangeOTPsRequest {} + +message GetExchangeOTPsResponse { + map otp_codes = 1; +} + +message DisableExchangeRequest { + string exchange = 1; +} + +message PairsSupported { + string available_pairs = 1; + string enabled_pairs = 2; +} + +message GetExchangeInfoResponse { + string name = 1; + bool enabled = 2; + bool verbose = 3; + bool using_sandbox = 4; + string http_timeout = 5; + string http_useragent = 6; + string http_proxy = 7; + string base_currencies = 8; + map supported_assets = 9; + bool authenticated_api = 10; +} + +message GetTickerRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; +} + +message CurrencyPair { + string delimiter = 1; + string base = 2; + string quote = 3; +} + +message TickerResponse { + CurrencyPair pair = 1; + int64 last_updated = 2; + string currency_pair = 3; + double last = 4; + double high = 5; + double low = 6; + double bid = 7; + double ask = 8; + double volume = 9; + double price_ath = 10; +} + +message GetTickersRequest {} + +message Tickers { + string exchange = 1; + repeated TickerResponse tickers = 2; +} + +message GetTickersResponse { + repeated Tickers tickers = 1; +} + +message GetOrderbookRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; +} + +message OrderbookItem { + double amount = 1; + double price = 2; + int64 id = 3; +} + +message OrderbookResponse { + CurrencyPair pair = 1; + string currency_pair = 2; + repeated OrderbookItem bids = 3; + repeated OrderbookItem asks = 4; + int64 last_updated = 5; + string asset_type = 6; +} + +message GetOrderbooksRequest {} + +message Orderbooks { + string exchange = 1; + repeated OrderbookResponse orderbooks = 2; +} + +message GetOrderbooksResponse { + repeated Orderbooks orderbooks = 1; +} + +message GetAccountInfoRequest { + string exchange = 1; +} + +message Account { + string id = 1; + repeated AccountCurrencyInfo currencies = 2; +} + +message AccountCurrencyInfo { + string currency = 1; + double total_value = 2; + double hold = 3; +} + +message GetAccountInfoResponse { + string exchange = 1; + repeated Account accounts = 2; +} + +message GetConfigRequest {} + +message GetConfigResponse { + bytes data = 1; +} + +message PortfolioAddress { + string address = 1; + string coin_type = 2; + string description = 3; + double balance = 4; +} + +message GetPortfolioRequest {} + +message GetPortfolioResponse { + repeated PortfolioAddress portfolio = 1; +} + +message GetPortfolioSummaryRequest {} + +message Coin { + string coin = 1; + double balance = 2; + string address = 3; + double percentage = 4; +} + +message OfflineCoinSummary { + string address = 1; + double balance = 2; + double percentage = 3; +} + +message OnlineCoinSummary { + double balance = 1; + double percentage = 2; +} + +message OfflineCoins { + repeated OfflineCoinSummary addresses = 1; +} + +message OnlineCoins { + map coins = 1; +} + +message GetPortfolioSummaryResponse { + repeated Coin coin_totals = 1; + repeated Coin coins_offline = 2; + map coins_offline_summary = 3; + repeated Coin coins_online = 4; + map coins_online_summary = 5; +} + +message AddPortfolioAddressRequest { + string address = 1; + string coin_type = 2; + string description = 3; + double balance = 4; + string supported_exchanges = 5; + bool cold_storage = 6; +} + +message RemovePortfolioAddressRequest { + string address = 1; + string coin_type = 2; + string description = 3; +} + +message GetForexProvidersRequest {} + +message ForexProvider { + string name = 1; + bool enabled = 2; + bool verbose = 3; + string rest_polling_delay = 4; + string api_key = 5; + int64 api_key_level =6; + bool primary_provider = 7; +} + +message GetForexProvidersResponse { + repeated ForexProvider forex_providers = 1; +} + +message GetForexRatesRequest {} + +message ForexRatesConversion { + string from = 1; + string to = 2; + double rate = 3; + double inverse_rate = 4; + +} +message GetForexRatesResponse { + repeated ForexRatesConversion forex_rates = 1; +} + +message OrderDetails { + string exchange = 1; + string id = 2; + string client_order_id = 3; + string base_currency = 4; + string quote_currency = 5; + string asset_type = 6; + string order_side = 7; + string order_type = 8; + int64 creation_time = 9; + int64 update_time = 10; + string status = 11; + double price = 12; + double amount = 13; + double open_volume = 14; + double fee = 15; + double cost = 16; + repeated TradeHistory trades = 17; +} + +message TradeHistory { + int64 creation_time = 1; + string id = 2; + double price = 3; + double amount = 4; + string exchange = 5; + string asset_type = 6; + string order_side = 7; + double fee = 8; +} + +message GetOrdersRequest { + string exchange = 1; + string asset_type = 2; + CurrencyPair pair = 3; +} + +message GetOrdersResponse { + repeated OrderDetails orders = 1; +} + +message GetOrderRequest { + string exchange = 1; + string order_id = 2; + CurrencyPair pair = 3; +} + +message SubmitOrderRequest { + string exchange = 1; + CurrencyPair pair = 2; + string side = 3; + string order_type = 4; + double amount = 5; + double price = 6; + string client_id = 7; + string asset_type = 8; +} + +message Trades { + double amount = 1; + double price = 2; + double fee = 3; + string fee_asset = 4; +} + +message SubmitOrderResponse { + bool order_placed = 1; + string order_id = 2; + repeated Trades trades= 3; +} + +message SimulateOrderRequest { + string exchange = 1; + CurrencyPair pair = 2; + double amount = 3; + string side = 4; +} + +message SimulateOrderResponse { + repeated OrderbookItem orders = 1; + double amount = 2; + double minimum_price = 3; + double maximum_price = 4; + double percentage_gain_loss = 5; + string status = 6; +} + +message WhaleBombRequest { + string exchange = 1; + CurrencyPair pair = 2; + double price_target = 3; + string side = 4; +} + +message CancelOrderRequest { + string exchange = 1; + string account_id = 2; + string order_id = 3; + CurrencyPair pair = 4; + string asset_type = 5; + string wallet_address = 6; + string side = 7; +} + +message CancelAllOrdersRequest { + string exchange = 1; +} + +message CancelAllOrdersResponse { + message Orders { + string exchange = 1; + map order_status = 2; + } + repeated Orders orders = 1; +} + +message GetEventsRequest {} + + +message ConditionParams { + string condition = 1; + double price = 2; + bool check_bids = 3; + bool check_bids_and_asks = 4; + double orderbook_amount = 5; +} + +message GetEventsResponse { + int64 id = 1; + string exchange = 2; + string item = 3; + ConditionParams condition_params = 4; + CurrencyPair pair = 5; + string action = 6; + bool executed = 7; +} + +message AddEventRequest { + string exchange = 1; + string item = 2; + ConditionParams condition_params = 3; + CurrencyPair pair = 4; + string asset_type = 5; + string action = 6; +} + +message AddEventResponse { + int64 id = 1; +} + +message RemoveEventRequest { + int64 id = 1; +} + +message GetCryptocurrencyDepositAddressesRequest { + string exchange = 1; +} + +message GetCryptocurrencyDepositAddressesResponse { + map addresses = 1; +} + +message GetCryptocurrencyDepositAddressRequest { + string exchange = 1; + string cryptocurrency = 2; +} + +message GetCryptocurrencyDepositAddressResponse { + string address = 1; +} + +message WithdrawFiatRequest { + string exchange = 1; + string currency = 2; + double amount = 3; + string description = 4; + string bank_account_id = 5; +} + +message WithdrawCryptoRequest { + string exchange = 1; + string address = 2; + string address_tag = 3; + string currency = 4; + double amount = 5; + double fee = 6; + string description = 7; +} + +message WithdrawResponse { + string id = 1; + string status = 2; +} + +message WithdrawalEventByIDRequest { + string id = 1; +} + +message WithdrawalEventByIDResponse { + WithdrawalEventResponse event = 2; +} + +message WithdrawalEventsByExchangeRequest { + string exchange = 1; + string id = 2; + int32 limit = 3; +} + +message WithdrawalEventsByDateRequest { + string exchange = 1; + string start = 2; + string end = 3; + int32 limit = 4; +} + +message WithdrawalEventsByExchangeResponse { + repeated WithdrawalEventResponse event = 2; +} + +message WithdrawalEventResponse { + string id = 2; + WithdrawlExchangeEvent exchange = 3; + WithdrawalRequestEvent request = 4; + google.protobuf.Timestamp created_at = 5; + google.protobuf.Timestamp updated_at = 6; +} + +message WithdrawlExchangeEvent { + string name = 1; + string id = 2; + string status = 3; +} + +message WithdrawalRequestEvent { + string currency = 2; + string description = 3; + double amount = 4; + int32 type = 5; + FiatWithdrawalEvent fiat = 6; + CryptoWithdrawalEvent crypto = 7; +} + +message FiatWithdrawalEvent { + string bank_name = 1; + string account_name = 2; + string account_number = 3; + string bsb = 4; + string swift = 5; + string iban = 6; +} + +message CryptoWithdrawalEvent { + string address = 1; + string address_tag = 2; + double fee = 3; +} + +message GetLoggerDetailsRequest { + string logger = 1; +} + +message GetLoggerDetailsResponse{ + bool info = 1; + bool debug = 2; + bool warn = 3; + bool error = 4; +} + +message SetLoggerDetailsRequest { + string logger = 1; + string level = 2; +} + +message GetExchangePairsRequest { + string exchange = 1; + string asset = 2; +} + +message GetExchangePairsResponse { + map supported_assets = 1; +} + +message SetExchangePairRequest { + string exchange = 1; + string asset_type = 2; + repeated CurrencyPair pairs = 3; + bool enable = 4; +} + +message GetOrderbookStreamRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; +} + +message GetExchangeOrderbookStreamRequest { + string exchange = 1; +} + +message GetTickerStreamRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; +} + +message GetExchangeTickerStreamRequest { + string exchange = 1; +} + +message GetAuditEventRequest { + string start_date = 1; + string end_date = 2; + string order_by = 3; + int32 limit = 4; + int32 offset = 5; +} + +message GetAuditEventResponse { + repeated AuditEvent events = 1; +} + +message GetSavedTradesRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; + string start = 4; + string end = 5; +} + +message SavedTrades { + double price = 1; + double amount = 2; + string side = 3; + string timestamp = 4; + string trade_id = 5; +} + +message SavedTradesResponse { + string exchange_name = 1; + string asset = 2; + CurrencyPair pair = 3; + repeated SavedTrades trades = 4; +} + +message ConvertTradesToCandlesRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; + string start = 4; + string end = 5; + int64 time_interval = 6; + bool sync = 7; + bool force = 8; +} + +message GetHistoricCandlesRequest { + string exchange = 1; + CurrencyPair pair = 2; + string asset_type = 3; + string start = 4; + string end = 5; + int64 time_interval = 6; + bool ex_request = 7; + bool sync = 8; + bool use_db = 9; + bool fill_missing_with_trades = 10; + bool force = 11; +} + +message GetHistoricCandlesResponse { + string exchange = 1; + CurrencyPair pair = 2; + string start = 3; + string end = 4; + string interval = 6; + repeated Candle candle = 5; +} + +message Candle { + string time = 1; + double low = 2; + double high = 3; + double open = 4; + double close = 5; + double volume = 6; +} + +message AuditEvent { + string type = 1; + string identifier = 2; + string message = 3; + string timestamp = 4; +} + +message GCTScript { + string UUID = 1; + string name = 2; + string path = 3; + string next_run = 4; +} + +message GCTScriptExecuteRequest { + GCTScript script = 1; +} + +message GCTScriptStopRequest { + GCTScript script = 1; +} + +message GCTScriptStopAllRequest{} +message GCTScriptStatusRequest {} +message GCTScriptListAllRequest{} + +message GCTScriptUploadRequest { + string script_name = 1; + string script_data = 2; + bytes data = 3; + bool archived = 4; + bool overwrite = 5; +} + +message GCTScriptReadScriptRequest{ + GCTScript script = 1; +} + +message GCTScriptQueryRequest{ + GCTScript script = 1; +} + +message GCTScriptAutoLoadRequest{ + string script = 1; + bool status = 2; +} + +message GCTScriptStatusResponse{ + string status = 1; + repeated GCTScript scripts = 2; +} + +message GCTScriptQueryResponse{ + string status = 1; + GCTScript script = 2; + string data = 3; +} + +message GenericResponse { + string status = 1; + string data = 2; +} + +message SetExchangeAssetRequest { + string exchange = 1; + string asset = 2; + bool enable = 3; +} + +message SetExchangeAllPairsRequest { + string exchange = 1; + bool enable = 2; +} + +message UpdateExchangeSupportedPairsRequest { + string exchange = 1; +} + +message GetExchangeAssetsRequest { + string exchange = 1; +} + +message GetExchangeAssetsResponse { + string assets = 1; +} + +message WebsocketGetInfoRequest { + string exchange = 1; +} + +message WebsocketGetInfoResponse { + string exchange = 1; + bool supported = 2; + bool enabled = 3; + bool authenticated_supported = 4; + bool authenticated = 5; + string running_url = 6; + string proxy_address = 7; +} + +message WebsocketSetEnabledRequest { + string exchange = 1; + bool enable = 2; +} + +message WebsocketGetSubscriptionsRequest { + string exchange = 1; +} + +message WebsocketSubscription { + string channel = 1; + string currency = 2; + string asset = 3; + string params = 4; +} + +message WebsocketGetSubscriptionsResponse { + string exchange = 1; + repeated WebsocketSubscription subscriptions = 2; +} + +message WebsocketSetProxyRequest { + string exchange = 1; + string proxy = 2; +} + +message WebsocketSetURLRequest { + string exchange = 1; + string url = 2; +} + +message FindMissingCandlePeriodsRequest { + string exchangeName = 1; + string assetType = 2; + CurrencyPair pair = 3; + int64 interval = 4; + string start = 5; + string end = 6; +} + +message FindMissingTradePeriodsRequest { + string exchangeName = 1; + string assetType = 2; + CurrencyPair pair = 3; + string start = 4; + string end = 5; +} + +message FindMissingIntervalsResponse { + string exchangeName = 1; + string assetType = 2; + CurrencyPair pair = 3; + repeated string missingPeriods = 4; + string status = 5; +} + +message SetExchangeTradeProcessingRequest { + string exchange = 1; + bool status = 2; +} + +service GoCryptoTrader { + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) { + option (google.api.http) = { + get :"/v1/getinfo" + }; + } + + rpc GetSubsystems (GetSubsystemsRequest) returns (GetSusbsytemsResponse) { + option (google.api.http) = { + get: "/v1/getsubsystems" + }; + } + + rpc EnableSubsystem (GenericSubsystemRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/enablesubsystem" + }; + } + + rpc DisableSubsystem (GenericSubsystemRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/disablesubsystem" + }; + } + + rpc GetRPCEndpoints (GetRPCEndpointsRequest) returns (GetRPCEndpointsResponse) { + option (google.api.http) = { + get: "/v1/getrpcendpoints" + }; + } + + rpc GetCommunicationRelayers (GetCommunicationRelayersRequest) returns (GetCommunicationRelayersResponse) { + option (google.api.http) = { + get: "/v1/getcommunicationrelayers" + }; + } + + rpc GetExchanges (GetExchangesRequest) returns (GetExchangesResponse) { + option (google.api.http) = { + get: "/v1/getexchanges" + }; + } + + rpc DisableExchange (GenericExchangeNameRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/disableexchange" + body: "*" + }; + } + + rpc GetExchangeInfo (GenericExchangeNameRequest) returns (GetExchangeInfoResponse) { + option (google.api.http) = { + get: "/v1/getexchangeinfo" + }; + } + + rpc GetExchangeOTPCode (GenericExchangeNameRequest) returns (GetExchangeOTPReponse) { + option (google.api.http) = { + get: "/v1/getexchangeotp" + }; + } + + rpc GetExchangeOTPCodes (GetExchangeOTPsRequest) returns (GetExchangeOTPsResponse) { + option (google.api.http) = { + get: "/v1/getexchangeotps" + }; + } + + rpc EnableExchange (GenericExchangeNameRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/enableexchange" + body: "*" + }; + } + + rpc GetTicker (GetTickerRequest) returns (TickerResponse) { + option (google.api.http) = { + post: "/v1/getticker" + body: "*" + }; + } + + rpc GetTickers (GetTickersRequest) returns (GetTickersResponse) { + option (google.api.http) = { + get: "/v1/gettickers" + }; + } + + rpc GetOrderbook (GetOrderbookRequest) returns (OrderbookResponse) { + option (google.api.http) = { + post: "/v1/getorderbook" + body: "*" + }; + } + + rpc GetOrderbooks (GetOrderbooksRequest) returns (GetOrderbooksResponse) { + option (google.api.http) = { + get: "/v1/getorderbooks" + }; + } + + rpc GetAccountInfo (GetAccountInfoRequest) returns (GetAccountInfoResponse) { + option (google.api.http) = { + get: "/v1/getaccountinfo" + }; + } + + rpc GetAccountInfoStream (GetAccountInfoRequest) returns (stream GetAccountInfoResponse) { + option (google.api.http) = { + get: "/v1/getaccountinfostream" + }; + } + + rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) { + option (google.api.http) = { + get: "/v1/getconfig" + }; + } + + rpc GetPortfolio (GetPortfolioRequest) returns (GetPortfolioResponse) { + option (google.api.http) = { + get: "/v1/getportfolio" + }; + } + + rpc GetPortfolioSummary (GetPortfolioSummaryRequest) returns (GetPortfolioSummaryResponse) { + option (google.api.http) = { + get: "/v1/getportfoliosummary" + }; + } + + + rpc AddPortfolioAddress (AddPortfolioAddressRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/addportfolioaddress" + body: "*" + }; + } + + rpc RemovePortfolioAddress (RemovePortfolioAddressRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/removeportfolioaddress" + body: "*" + }; + } + + rpc GetForexProviders (GetForexProvidersRequest) returns (GetForexProvidersResponse) { + option (google.api.http) = { + get: "/v1/getforexproviders" + }; + } + + rpc GetForexRates (GetForexRatesRequest) returns (GetForexRatesResponse) { + option (google.api.http) = { + get: "/v1/getforexrates" + }; + } + + rpc GetOrders (GetOrdersRequest) returns (GetOrdersResponse) { + option (google.api.http) = { + post: "/v1/getorders" + body: "*" + }; + } + + rpc GetOrder (GetOrderRequest) returns (OrderDetails) { + option (google.api.http) = { + post: "/v1/getorder" + body: "*" + }; + } + + rpc SubmitOrder (SubmitOrderRequest) returns (SubmitOrderResponse) { + option (google.api.http) = { + post: "/v1/submitorder" + body: "*" + }; + } + + rpc SimulateOrder (SimulateOrderRequest) returns (SimulateOrderResponse) { + option (google.api.http) = { + post: "/v1/simulateorder" + body: "*" + }; + } + + rpc WhaleBomb (WhaleBombRequest) returns (SimulateOrderResponse) { + option (google.api.http) = { + post: "/v1/whalebomb" + body: "*" + }; + } + + rpc CancelOrder (CancelOrderRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/cancelorder" + body: "*" + }; + } + + rpc CancelAllOrders (CancelAllOrdersRequest) returns (CancelAllOrdersResponse) { + option (google.api.http) = { + post: "/v1/cancelallorders" + body: "*" + }; + } + + rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) { + option (google.api.http) = { + get: "/v1/getevents" + }; + } + + rpc AddEvent(AddEventRequest) returns (AddEventResponse) { + option (google.api.http) = { + post: "/v1/addevent" + body: "*" + }; + } + + rpc RemoveEvent(RemoveEventRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/removeevent" + body: "*" + }; + } + + rpc GetCryptocurrencyDepositAddresses(GetCryptocurrencyDepositAddressesRequest) returns (GetCryptocurrencyDepositAddressesResponse) { + option (google.api.http) = { + post: "/v1/getcryptodepositaddresses" + body: "*" + }; + } + + rpc GetCryptocurrencyDepositAddress(GetCryptocurrencyDepositAddressRequest) returns (GetCryptocurrencyDepositAddressResponse) { + option (google.api.http) = { + post: "/v1/getcryptodepositaddress" + body: "*" + }; + } + + + rpc WithdrawFiatFunds(WithdrawFiatRequest) returns (WithdrawResponse) { + option (google.api.http) = { + post: "/v1/withdrawfiatfunds" + body: "*" + }; + } + + rpc WithdrawCryptocurrencyFunds(WithdrawCryptoRequest) returns (WithdrawResponse) { + option (google.api.http) = { + post: "/v1/withdrawithdrawcryptofundswfiatfunds" + body: "*" + }; + } + + rpc WithdrawalEventByID(WithdrawalEventByIDRequest) returns (WithdrawalEventByIDResponse) { + option (google.api.http) = { + post: "/v1/withdrawaleventbyid" + body: "*" + }; + } + + rpc WithdrawalEventsByExchange(WithdrawalEventsByExchangeRequest) returns (WithdrawalEventsByExchangeResponse) { + option (google.api.http) = { + post: "/v1/withdrawaleventbyid" + body: "*" + }; + } + + rpc WithdrawalEventsByDate(WithdrawalEventsByDateRequest) returns (WithdrawalEventsByExchangeResponse) { + option (google.api.http) = { + post: "/v1/withdrawaleventbydate" + body: "*" + }; + } + + rpc GetLoggerDetails(GetLoggerDetailsRequest) returns (GetLoggerDetailsResponse) { + option (google.api.http) = { + get: "/v1/getloggerdetails" + }; + } + + rpc SetLoggerDetails(SetLoggerDetailsRequest) returns (GetLoggerDetailsResponse) { + option (google.api.http) = { + post: "/v1/setloggerdetails", + body: "*" + }; + } + + rpc GetExchangePairs(GetExchangePairsRequest) returns (GetExchangePairsResponse) { + option (google.api.http) = { + post: "/v1/getexchangepairs", + body: "*" + }; + } + + rpc SetExchangePair(SetExchangePairRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/setexchangepair", + body: "*" + }; + } + + rpc GetOrderbookStream(GetOrderbookStreamRequest) returns (stream OrderbookResponse) { + option (google.api.http) = { + get: "/v1/getorderbookstream" + }; + } + + rpc GetExchangeOrderbookStream(GetExchangeOrderbookStreamRequest) returns (stream OrderbookResponse) { + option (google.api.http) = { + get: "/v1/getexchangeorderbookstream" + }; + } + + rpc GetTickerStream(GetTickerStreamRequest) returns (stream TickerResponse) { + option (google.api.http) = { + get: "/v1/gettickerstream" + }; + } + + rpc GetExchangeTickerStream(GetExchangeTickerStreamRequest) returns (stream TickerResponse) { + option (google.api.http) = { + get: "/v1/getexchangetickerstream", + }; + } + + rpc GetAuditEvent(GetAuditEventRequest) returns (GetAuditEventResponse) { + option (google.api.http) = { + get: "/v1/getauditevent", + }; + } + + rpc GCTScriptExecute(GCTScriptExecuteRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/gctscript/execute", + }; + } + + rpc GCTScriptUpload(GCTScriptUploadRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/gctscript/upload", + body: "*" + }; + } + + rpc GCTScriptReadScript(GCTScriptReadScriptRequest) returns (GCTScriptQueryResponse) { + option (google.api.http) = { + post: "/v1/gctscript/read", + body: "*" + }; + } + + rpc GCTScriptStatus(GCTScriptStatusRequest) returns (GCTScriptStatusResponse) { + option (google.api.http) = { + get: "/v1/gctscript/status", + }; + } + + rpc GCTScriptQuery(GCTScriptQueryRequest) returns (GCTScriptQueryResponse) { + option (google.api.http) = { + get: "/v1/gctscript/query", + }; + } + + rpc GCTScriptStop(GCTScriptStopRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/gctscript/stop", + body: "*" + }; + } + + rpc GCTScriptStopAll(GCTScriptStopAllRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/gctscript/stop", + body: "*" + }; + } + + rpc GCTScriptListAll(GCTScriptListAllRequest) returns (GCTScriptStatusResponse) { + option (google.api.http) = { + post: "/v1/gctscript/stop", + body: "*" + }; + } + rpc GCTScriptAutoLoadToggle(GCTScriptAutoLoadRequest) returns (GenericResponse) { + option (google.api.http) = { + post: "/v1/gctscript/autoload", + body: "*" + }; + } + + rpc GetHistoricCandles(GetHistoricCandlesRequest) returns (GetHistoricCandlesResponse) { + option (google.api.http) = { + get: "/v1/gethistoriccandles" + }; + } + + rpc SetExchangeAsset(SetExchangeAssetRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/setexchangeasset" + }; + } + + rpc SetAllExchangePairs(SetExchangeAllPairsRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/setallexchangepairs" + }; + } + + rpc UpdateExchangeSupportedPairs(UpdateExchangeSupportedPairsRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/updateexchangesupportedpairs" + }; + } + + rpc GetExchangeAssets(GetExchangeAssetsRequest) returns (GetExchangeAssetsResponse) { + option (google.api.http) = { + get: "/v1/getexchangeassets" + }; + } + + rpc WebsocketGetInfo(WebsocketGetInfoRequest) returns (WebsocketGetInfoResponse) { + option (google.api.http) = { + get: "/v1/websocketgetinfo" + }; + } + + rpc WebsocketSetEnabled(WebsocketSetEnabledRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/websocketsetenabled" + }; + } + + rpc WebsocketGetSubscriptions(WebsocketGetSubscriptionsRequest) returns (WebsocketGetSubscriptionsResponse) { + option (google.api.http) = { + get: "/v1/websocketgetsubscriptions" + }; + } + + rpc WebsocketSetProxy(WebsocketSetProxyRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/websocketsetproxy" + }; + } + + rpc WebsocketSetURL(WebsocketSetURLRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/websocketseturl" + }; + } + + rpc GetRecentTrades(GetSavedTradesRequest) returns (SavedTradesResponse) { + option (google.api.http) = { + get: "/v1/getsavedtrades" + }; + } + + rpc GetHistoricTrades(GetSavedTradesRequest) returns (stream SavedTradesResponse) { + option (google.api.http) = { + get: "/v1/getsavedtrades" + }; + } + + rpc GetSavedTrades(GetSavedTradesRequest) returns (SavedTradesResponse) { + option (google.api.http) = { + get: "/v1/getsavedtrades" + }; + } + + rpc ConvertTradesToCandles (ConvertTradesToCandlesRequest) returns (GetHistoricCandlesResponse) { + option (google.api.http) = { + get: "/v1/converttradestocandles" + }; + } + + rpc FindMissingSavedCandleIntervals (FindMissingCandlePeriodsRequest) returns (FindMissingIntervalsResponse) { + option (google.api.http) = { + get: "/v1/findmissingsavedcandleintervals" + }; + } + + rpc FindMissingSavedTradeIntervals (FindMissingTradePeriodsRequest) returns (FindMissingIntervalsResponse) { + option (google.api.http) = { + get: "/v1/findmissingsavedtradeintervals" + }; + } + + rpc SetExchangeTradeProcessing (SetExchangeTradeProcessingRequest) returns (GenericResponse) { + option (google.api.http) = { + get: "/v1/setexchangetradeprocessing" + }; + } } \ No newline at end of file diff --git a/gctrpc/rpc.swagger.json b/gctrpc/rpc.swagger.json index 4c6dbfc8..e725d358 100644 --- a/gctrpc/rpc.swagger.json +++ b/gctrpc/rpc.swagger.json @@ -13,7 +13,7 @@ "paths": { "/v1/addevent": { "post": { - "operationId": "GoCryptoTrader_AddEvent", + "operationId": "AddEvent", "responses": { "200": { "description": "A successful response.", @@ -45,7 +45,7 @@ }, "/v1/addportfolioaddress": { "post": { - "operationId": "GoCryptoTrader_AddPortfolioAddress", + "operationId": "AddPortfolioAddress", "responses": { "200": { "description": "A successful response.", @@ -77,7 +77,7 @@ }, "/v1/cancelallorders": { "post": { - "operationId": "GoCryptoTrader_CancelAllOrders", + "operationId": "CancelAllOrders", "responses": { "200": { "description": "A successful response.", @@ -109,7 +109,7 @@ }, "/v1/cancelorder": { "post": { - "operationId": "GoCryptoTrader_CancelOrder", + "operationId": "CancelOrder", "responses": { "200": { "description": "A successful response.", @@ -139,9 +139,96 @@ ] } }, + "/v1/converttradestocandles": { + "get": { + "operationId": "ConvertTradesToCandles", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/gctrpcGetHistoricCandlesResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "exchange", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.delimiter", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.base", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.quote", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "asset_type", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "start", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "time_interval", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "sync", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + }, + { + "name": "force", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + } + ], + "tags": [ + "GoCryptoTrader" + ] + } + }, "/v1/disableexchange": { "post": { - "operationId": "GoCryptoTrader_DisableExchange", + "operationId": "DisableExchange", "responses": { "200": { "description": "A successful response.", @@ -173,7 +260,7 @@ }, "/v1/disablesubsystem": { "get": { - "operationId": "GoCryptoTrader_DisableSubsystem", + "operationId": "DisableSubsystem", "responses": { "200": { "description": "A successful response.", @@ -203,7 +290,7 @@ }, "/v1/enableexchange": { "post": { - "operationId": "GoCryptoTrader_EnableExchange", + "operationId": "EnableExchange", "responses": { "200": { "description": "A successful response.", @@ -235,7 +322,7 @@ }, "/v1/enablesubsystem": { "get": { - "operationId": "GoCryptoTrader_EnableSubsystem", + "operationId": "EnableSubsystem", "responses": { "200": { "description": "A successful response.", @@ -263,9 +350,148 @@ ] } }, + "/v1/findmissingsavedcandleintervals": { + "get": { + "operationId": "FindMissingSavedCandleIntervals", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/gctrpcFindMissingIntervalsResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "exchangeName", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "assetType", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.delimiter", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.base", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.quote", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "interval", + "in": "query", + "required": false, + "type": "string", + "format": "int64" + }, + { + "name": "start", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "GoCryptoTrader" + ] + } + }, + "/v1/findmissingsavedtradeintervals": { + "get": { + "operationId": "FindMissingSavedTradeIntervals", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/gctrpcFindMissingIntervalsResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "exchangeName", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "assetType", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.delimiter", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.base", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.quote", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "start", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "GoCryptoTrader" + ] + } + }, "/v1/gctscript/autoload": { "post": { - "operationId": "GoCryptoTrader_GCTScriptAutoLoadToggle", + "operationId": "GCTScriptAutoLoadToggle", "responses": { "200": { "description": "A successful response.", @@ -297,7 +523,7 @@ }, "/v1/gctscript/execute": { "get": { - "operationId": "GoCryptoTrader_GCTScriptExecute", + "operationId": "GCTScriptExecute", "responses": { "200": { "description": "A successful response.", @@ -345,7 +571,7 @@ }, "/v1/gctscript/query": { "get": { - "operationId": "GoCryptoTrader_GCTScriptQuery", + "operationId": "GCTScriptQuery", "responses": { "200": { "description": "A successful response.", @@ -393,7 +619,7 @@ }, "/v1/gctscript/read": { "post": { - "operationId": "GoCryptoTrader_GCTScriptReadScript", + "operationId": "GCTScriptReadScript", "responses": { "200": { "description": "A successful response.", @@ -425,7 +651,7 @@ }, "/v1/gctscript/status": { "get": { - "operationId": "GoCryptoTrader_GCTScriptStatus", + "operationId": "GCTScriptStatus", "responses": { "200": { "description": "A successful response.", @@ -447,7 +673,7 @@ }, "/v1/gctscript/stop": { "post": { - "operationId": "GoCryptoTrader_GCTScriptListAll", + "operationId": "GCTScriptListAll", "responses": { "200": { "description": "A successful response.", @@ -479,7 +705,7 @@ }, "/v1/gctscript/upload": { "post": { - "operationId": "GoCryptoTrader_GCTScriptUpload", + "operationId": "GCTScriptUpload", "responses": { "200": { "description": "A successful response.", @@ -511,7 +737,7 @@ }, "/v1/getaccountinfo": { "get": { - "operationId": "GoCryptoTrader_GetAccountInfo", + "operationId": "GetAccountInfo", "responses": { "200": { "description": "A successful response.", @@ -541,7 +767,7 @@ }, "/v1/getaccountinfostream": { "get": { - "operationId": "GoCryptoTrader_GetAccountInfoStream", + "operationId": "GetAccountInfoStream", "responses": { "200": { "description": "A successful response.(streaming responses)", @@ -580,7 +806,7 @@ }, "/v1/getauditevent": { "get": { - "operationId": "GoCryptoTrader_GetAuditEvent", + "operationId": "GetAuditEvent", "responses": { "200": { "description": "A successful response.", @@ -636,7 +862,7 @@ }, "/v1/getcommunicationrelayers": { "get": { - "operationId": "GoCryptoTrader_GetCommunicationRelayers", + "operationId": "GetCommunicationRelayers", "responses": { "200": { "description": "A successful response.", @@ -658,7 +884,7 @@ }, "/v1/getconfig": { "get": { - "operationId": "GoCryptoTrader_GetConfig", + "operationId": "GetConfig", "responses": { "200": { "description": "A successful response.", @@ -680,7 +906,7 @@ }, "/v1/getcryptodepositaddress": { "post": { - "operationId": "GoCryptoTrader_GetCryptocurrencyDepositAddress", + "operationId": "GetCryptocurrencyDepositAddress", "responses": { "200": { "description": "A successful response.", @@ -712,7 +938,7 @@ }, "/v1/getcryptodepositaddresses": { "post": { - "operationId": "GoCryptoTrader_GetCryptocurrencyDepositAddresses", + "operationId": "GetCryptocurrencyDepositAddresses", "responses": { "200": { "description": "A successful response.", @@ -744,7 +970,7 @@ }, "/v1/getevents": { "get": { - "operationId": "GoCryptoTrader_GetEvents", + "operationId": "GetEvents", "responses": { "200": { "description": "A successful response.", @@ -766,7 +992,7 @@ }, "/v1/getexchangeassets": { "get": { - "operationId": "GoCryptoTrader_GetExchangeAssets", + "operationId": "GetExchangeAssets", "responses": { "200": { "description": "A successful response.", @@ -796,7 +1022,7 @@ }, "/v1/getexchangeinfo": { "get": { - "operationId": "GoCryptoTrader_GetExchangeInfo", + "operationId": "GetExchangeInfo", "responses": { "200": { "description": "A successful response.", @@ -826,7 +1052,7 @@ }, "/v1/getexchangeorderbookstream": { "get": { - "operationId": "GoCryptoTrader_GetExchangeOrderbookStream", + "operationId": "GetExchangeOrderbookStream", "responses": { "200": { "description": "A successful response.(streaming responses)", @@ -865,7 +1091,7 @@ }, "/v1/getexchangeotp": { "get": { - "operationId": "GoCryptoTrader_GetExchangeOTPCode", + "operationId": "GetExchangeOTPCode", "responses": { "200": { "description": "A successful response.", @@ -895,7 +1121,7 @@ }, "/v1/getexchangeotps": { "get": { - "operationId": "GoCryptoTrader_GetExchangeOTPCodes", + "operationId": "GetExchangeOTPCodes", "responses": { "200": { "description": "A successful response.", @@ -917,7 +1143,7 @@ }, "/v1/getexchangepairs": { "post": { - "operationId": "GoCryptoTrader_GetExchangePairs", + "operationId": "GetExchangePairs", "responses": { "200": { "description": "A successful response.", @@ -949,7 +1175,7 @@ }, "/v1/getexchanges": { "get": { - "operationId": "GoCryptoTrader_GetExchanges", + "operationId": "GetExchanges", "responses": { "200": { "description": "A successful response.", @@ -980,7 +1206,7 @@ }, "/v1/getexchangetickerstream": { "get": { - "operationId": "GoCryptoTrader_GetExchangeTickerStream", + "operationId": "GetExchangeTickerStream", "responses": { "200": { "description": "A successful response.(streaming responses)", @@ -1019,7 +1245,7 @@ }, "/v1/getforexproviders": { "get": { - "operationId": "GoCryptoTrader_GetForexProviders", + "operationId": "GetForexProviders", "responses": { "200": { "description": "A successful response.", @@ -1041,7 +1267,7 @@ }, "/v1/getforexrates": { "get": { - "operationId": "GoCryptoTrader_GetForexRates", + "operationId": "GetForexRates", "responses": { "200": { "description": "A successful response.", @@ -1063,7 +1289,7 @@ }, "/v1/gethistoriccandles": { "get": { - "operationId": "GoCryptoTrader_GetHistoricCandles", + "operationId": "GetHistoricCandles", "responses": { "200": { "description": "A successful response.", @@ -1113,15 +1339,13 @@ "name": "start", "in": "query", "required": false, - "type": "string", - "format": "int64" + "type": "string" }, { "name": "end", "in": "query", "required": false, - "type": "string", - "format": "int64" + "type": "string" }, { "name": "time_interval", @@ -1150,6 +1374,20 @@ "required": false, "type": "boolean", "format": "boolean" + }, + { + "name": "fill_missing_with_trades", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + }, + { + "name": "force", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" } ], "tags": [ @@ -1159,7 +1397,7 @@ }, "/v1/getinfo": { "get": { - "operationId": "GoCryptoTrader_GetInfo", + "operationId": "GetInfo", "responses": { "200": { "description": "A successful response.", @@ -1181,7 +1419,7 @@ }, "/v1/getloggerdetails": { "get": { - "operationId": "GoCryptoTrader_GetLoggerDetails", + "operationId": "GetLoggerDetails", "responses": { "200": { "description": "A successful response.", @@ -1211,7 +1449,7 @@ }, "/v1/getorder": { "post": { - "operationId": "GoCryptoTrader_GetOrder", + "operationId": "GetOrder", "responses": { "200": { "description": "A successful response.", @@ -1243,7 +1481,7 @@ }, "/v1/getorderbook": { "post": { - "operationId": "GoCryptoTrader_GetOrderbook", + "operationId": "GetOrderbook", "responses": { "200": { "description": "A successful response.", @@ -1275,7 +1513,7 @@ }, "/v1/getorderbooks": { "get": { - "operationId": "GoCryptoTrader_GetOrderbooks", + "operationId": "GetOrderbooks", "responses": { "200": { "description": "A successful response.", @@ -1297,7 +1535,7 @@ }, "/v1/getorderbookstream": { "get": { - "operationId": "GoCryptoTrader_GetOrderbookStream", + "operationId": "GetOrderbookStream", "responses": { "200": { "description": "A successful response.(streaming responses)", @@ -1360,7 +1598,7 @@ }, "/v1/getorders": { "post": { - "operationId": "GoCryptoTrader_GetOrders", + "operationId": "GetOrders", "responses": { "200": { "description": "A successful response.", @@ -1392,7 +1630,7 @@ }, "/v1/getportfolio": { "get": { - "operationId": "GoCryptoTrader_GetPortfolio", + "operationId": "GetPortfolio", "responses": { "200": { "description": "A successful response.", @@ -1414,7 +1652,7 @@ }, "/v1/getportfoliosummary": { "get": { - "operationId": "GoCryptoTrader_GetPortfolioSummary", + "operationId": "GetPortfolioSummary", "responses": { "200": { "description": "A successful response.", @@ -1436,7 +1674,7 @@ }, "/v1/getrpcendpoints": { "get": { - "operationId": "GoCryptoTrader_GetRPCEndpoints", + "operationId": "GetRPCEndpoints", "responses": { "200": { "description": "A successful response.", @@ -1456,9 +1694,75 @@ ] } }, + "/v1/getsavedtrades": { + "get": { + "operationId": "GetSavedTrades", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/gctrpcSavedTradesResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "exchange", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.delimiter", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.base", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "pair.quote", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "asset_type", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "start", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "end", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "GoCryptoTrader" + ] + } + }, "/v1/getsubsystems": { "get": { - "operationId": "GoCryptoTrader_GetSubsystems", + "operationId": "GetSubsystems", "responses": { "200": { "description": "A successful response.", @@ -1480,7 +1784,7 @@ }, "/v1/getticker": { "post": { - "operationId": "GoCryptoTrader_GetTicker", + "operationId": "GetTicker", "responses": { "200": { "description": "A successful response.", @@ -1512,7 +1816,7 @@ }, "/v1/gettickers": { "get": { - "operationId": "GoCryptoTrader_GetTickers", + "operationId": "GetTickers", "responses": { "200": { "description": "A successful response.", @@ -1534,7 +1838,7 @@ }, "/v1/gettickerstream": { "get": { - "operationId": "GoCryptoTrader_GetTickerStream", + "operationId": "GetTickerStream", "responses": { "200": { "description": "A successful response.(streaming responses)", @@ -1597,7 +1901,7 @@ }, "/v1/removeevent": { "post": { - "operationId": "GoCryptoTrader_RemoveEvent", + "operationId": "RemoveEvent", "responses": { "200": { "description": "A successful response.", @@ -1629,7 +1933,7 @@ }, "/v1/removeportfolioaddress": { "post": { - "operationId": "GoCryptoTrader_RemovePortfolioAddress", + "operationId": "RemovePortfolioAddress", "responses": { "200": { "description": "A successful response.", @@ -1661,7 +1965,7 @@ }, "/v1/setallexchangepairs": { "get": { - "operationId": "GoCryptoTrader_SetAllExchangePairs", + "operationId": "SetAllExchangePairs", "responses": { "200": { "description": "A successful response.", @@ -1698,7 +2002,7 @@ }, "/v1/setexchangeasset": { "get": { - "operationId": "GoCryptoTrader_SetExchangeAsset", + "operationId": "SetExchangeAsset", "responses": { "200": { "description": "A successful response.", @@ -1741,7 +2045,7 @@ }, "/v1/setexchangepair": { "post": { - "operationId": "GoCryptoTrader_SetExchangePair", + "operationId": "SetExchangePair", "responses": { "200": { "description": "A successful response.", @@ -1771,9 +2075,46 @@ ] } }, + "/v1/setexchangetradeprocessing": { + "get": { + "operationId": "SetExchangeTradeProcessing", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/gctrpcGenericResponse" + } + }, + "default": { + "description": "An unexpected error response", + "schema": { + "$ref": "#/definitions/runtimeError" + } + } + }, + "parameters": [ + { + "name": "exchange", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "status", + "in": "query", + "required": false, + "type": "boolean", + "format": "boolean" + } + ], + "tags": [ + "GoCryptoTrader" + ] + } + }, "/v1/setloggerdetails": { "post": { - "operationId": "GoCryptoTrader_SetLoggerDetails", + "operationId": "SetLoggerDetails", "responses": { "200": { "description": "A successful response.", @@ -1805,7 +2146,7 @@ }, "/v1/simulateorder": { "post": { - "operationId": "GoCryptoTrader_SimulateOrder", + "operationId": "SimulateOrder", "responses": { "200": { "description": "A successful response.", @@ -1837,7 +2178,7 @@ }, "/v1/submitorder": { "post": { - "operationId": "GoCryptoTrader_SubmitOrder", + "operationId": "SubmitOrder", "responses": { "200": { "description": "A successful response.", @@ -1869,7 +2210,7 @@ }, "/v1/updateexchangesupportedpairs": { "get": { - "operationId": "GoCryptoTrader_UpdateExchangeSupportedPairs", + "operationId": "UpdateExchangeSupportedPairs", "responses": { "200": { "description": "A successful response.", @@ -1899,7 +2240,7 @@ }, "/v1/websocketgetinfo": { "get": { - "operationId": "GoCryptoTrader_WebsocketGetInfo", + "operationId": "WebsocketGetInfo", "responses": { "200": { "description": "A successful response.", @@ -1929,7 +2270,7 @@ }, "/v1/websocketgetsubscriptions": { "get": { - "operationId": "GoCryptoTrader_WebsocketGetSubscriptions", + "operationId": "WebsocketGetSubscriptions", "responses": { "200": { "description": "A successful response.", @@ -1959,7 +2300,7 @@ }, "/v1/websocketsetenabled": { "get": { - "operationId": "GoCryptoTrader_WebsocketSetEnabled", + "operationId": "WebsocketSetEnabled", "responses": { "200": { "description": "A successful response.", @@ -1996,7 +2337,7 @@ }, "/v1/websocketsetproxy": { "get": { - "operationId": "GoCryptoTrader_WebsocketSetProxy", + "operationId": "WebsocketSetProxy", "responses": { "200": { "description": "A successful response.", @@ -2032,7 +2373,7 @@ }, "/v1/websocketseturl": { "get": { - "operationId": "GoCryptoTrader_WebsocketSetURL", + "operationId": "WebsocketSetURL", "responses": { "200": { "description": "A successful response.", @@ -2068,7 +2409,7 @@ }, "/v1/whalebomb": { "post": { - "operationId": "GoCryptoTrader_WhaleBomb", + "operationId": "WhaleBomb", "responses": { "200": { "description": "A successful response.", @@ -2100,7 +2441,7 @@ }, "/v1/withdrawaleventbydate": { "post": { - "operationId": "GoCryptoTrader_WithdrawalEventsByDate", + "operationId": "WithdrawalEventsByDate", "responses": { "200": { "description": "A successful response.", @@ -2132,7 +2473,7 @@ }, "/v1/withdrawaleventbyid": { "post": { - "operationId": "GoCryptoTrader_WithdrawalEventsByExchange", + "operationId": "WithdrawalEventsByExchange", "responses": { "200": { "description": "A successful response.", @@ -2164,7 +2505,7 @@ }, "/v1/withdrawfiatfunds": { "post": { - "operationId": "GoCryptoTrader_WithdrawFiatFunds", + "operationId": "WithdrawFiatFunds", "responses": { "200": { "description": "A successful response.", @@ -2196,7 +2537,7 @@ }, "/v1/withdrawithdrawcryptofundswfiatfunds": { "post": { - "operationId": "GoCryptoTrader_WithdrawCryptocurrencyFunds", + "operationId": "WithdrawCryptocurrencyFunds", "responses": { "200": { "description": "A successful response.", @@ -2395,8 +2736,7 @@ "type": "object", "properties": { "time": { - "type": "string", - "format": "int64" + "type": "string" }, "low": { "type": "number", @@ -2528,6 +2868,29 @@ } } }, + "gctrpcFindMissingIntervalsResponse": { + "type": "object", + "properties": { + "exchangeName": { + "type": "string" + }, + "assetType": { + "type": "string" + }, + "pair": { + "$ref": "#/definitions/gctrpcCurrencyPair" + }, + "missingPeriods": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string" + } + } + }, "gctrpcForexProvider": { "type": "object", "properties": { @@ -2940,12 +3303,10 @@ "$ref": "#/definitions/gctrpcCurrencyPair" }, "start": { - "type": "string", - "format": "int64" + "type": "string" }, "end": { - "type": "string", - "format": "int64" + "type": "string" }, "interval": { "type": "string" @@ -3414,6 +3775,48 @@ } } }, + "gctrpcSavedTrades": { + "type": "object", + "properties": { + "price": { + "type": "number", + "format": "double" + }, + "amount": { + "type": "number", + "format": "double" + }, + "side": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "trade_id": { + "type": "string" + } + } + }, + "gctrpcSavedTradesResponse": { + "type": "object", + "properties": { + "exchange_name": { + "type": "string" + }, + "asset": { + "type": "string" + }, + "pair": { + "$ref": "#/definitions/gctrpcCurrencyPair" + }, + "trades": { + "type": "array", + "items": { + "$ref": "#/definitions/gctrpcSavedTrades" + } + } + } + }, "gctrpcSetExchangePairRequest": { "type": "object", "properties": { diff --git a/gctscript/vm/vm_test.go b/gctscript/vm/vm_test.go index 3abdfebd..eeab47fd 100644 --- a/gctscript/vm/vm_test.go +++ b/gctscript/vm/vm_test.go @@ -32,7 +32,9 @@ var ( func TestMain(m *testing.M) { c := log.GenDefaultSettings() c.Enabled = convert.BoolPtr(false) + log.RWM.Lock() log.GlobalLogConfig = &c + log.RWM.Unlock() GCTScriptConfig = configHelper(true, true, maxTestVirtualMachines) os.Exit(m.Run()) } diff --git a/log/logger_setup.go b/log/logger_setup.go index bde00607..6ab7d72f 100644 --- a/log/logger_setup.go +++ b/log/logger_setup.go @@ -87,6 +87,7 @@ func SetupSubLoggers(s []SubLoggerConfig) { // SetupGlobalLogger setup the global loggers with the default global config values func SetupGlobalLogger() { + RWM.Lock() if FileLoggingConfiguredCorrectly { GlobalLogFile = &Rotate{ FileName: GlobalLogConfig.LoggerFileConfig.FileName, @@ -101,6 +102,7 @@ func SetupGlobalLogger() { } logger = newLogger(GlobalLogConfig) + RWM.Unlock() } func splitLevel(level string) (l Levels) { @@ -156,4 +158,5 @@ func init() { Ticker = registerNewSubLogger("TICKER") OrderBook = registerNewSubLogger("ORDERBOOK") + Trade = registerNewSubLogger("TRADE") } diff --git a/log/logger_test.go b/log/logger_test.go index 8dcfed49..4ebef873 100644 --- a/log/logger_test.go +++ b/log/logger_test.go @@ -40,8 +40,9 @@ func setupTestLoggers() { Output: "stdout", }}, } - + RWM.Lock() GlobalLogConfig = &logTest + RWM.Unlock() SetupGlobalLogger() SetupSubLoggers(logTest.SubLoggers) } @@ -50,8 +51,10 @@ func SetupDisabled() { logTest := Config{ Enabled: convert.BoolPtr(false), } - + RWM.Lock() GlobalLogConfig = &logTest + RWM.Unlock() + SetupGlobalLogger() SetupSubLoggers(logTest.SubLoggers) } diff --git a/log/loggers.go b/log/loggers.go index 2bcd4e54..59023395 100644 --- a/log/loggers.go +++ b/log/loggers.go @@ -168,10 +168,13 @@ func displayError(err error) { } func enabled() bool { - RWM.RLock() - defer RWM.RUnlock() - if GlobalLogConfig.Enabled == nil { + RWM.Lock() + defer RWM.Unlock() + if GlobalLogConfig == nil || GlobalLogConfig.Enabled == nil { return false } - return *GlobalLogConfig.Enabled + if *GlobalLogConfig.Enabled { + return true + } + return false } diff --git a/log/sublogger_types.go b/log/sublogger_types.go index 2ff5749c..ec467f4b 100644 --- a/log/sublogger_types.go +++ b/log/sublogger_types.go @@ -25,4 +25,5 @@ var ( Ticker *subLogger OrderBook *subLogger + Trade *subLogger ) diff --git a/main.go b/main.go index 8d3148df..2928838e 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/dispatch" "github.com/thrasher-corp/gocryptotrader/engine" "github.com/thrasher-corp/gocryptotrader/exchanges/request" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/gctscript" gctscriptVM "github.com/thrasher-corp/gocryptotrader/gctscript/vm" gctlog "github.com/thrasher-corp/gocryptotrader/log" @@ -85,6 +86,7 @@ func main() { flag.StringVar(&settings.HTTPUserAgent, "httpuseragent", "", "sets the HTTP user agent") flag.StringVar(&settings.HTTPProxy, "httpproxy", "", "sets the HTTP proxy server") flag.BoolVar(&settings.EnableExchangeHTTPDebugging, "exchangehttpdebugging", false, "sets the exchanges HTTP debugging") + flag.DurationVar(&settings.TradeBufferProcessingInterval, "tradeprocessinginterval", trade.DefaultProcessorIntervalTime, "sets the interval to save trade buffer data to the database") // Common tuning settings flag.DurationVar(&settings.GlobalHTTPTimeout, "globalhttptimeout", time.Duration(0), "sets common HTTP timeout value for HTTP requests") diff --git a/testdata/configtest.json b/testdata/configtest.json index 57da70e6..6dcef525 100644 --- a/testdata/configtest.json +++ b/testdata/configtest.json @@ -2371,7 +2371,7 @@ } }, "spot": { - "enabled": "BTC/USDT", + "enabled": "BTC/USDT,GOM2/USDT", "available": "ABBC/BTC,ABBC/USDT,ABT/ETH,ABT/USDT,ABYSS/ETH,ACDC/BTC,ACDC/USDT,ADI/ETH,ADK/BTC,ADN/BTC,AE/BTC,AE/USDT,AIDOC/BTC,AION/BTC,AIPE/USDT,AIT/USDT,ALI/ETH,ALX/ETH,APL/ETH,ATX/BTC,BAAS/BTC,BABA/USDT,BAT/BTC,BCH/USDT,BETHER/ETH,BEZ/BTC,BGC/USDT,BKG/BTC,BNB/USDT,BNT/BTC,BOA/USDT,BSTN/ETH,BSV/USDT,BTC/USDT,BTNT/BTC,BTSC/BTC,BTT/USDT,BU/ETH,BVT/ETH,CAN/ETH,CCC/ETH,CCE/USDT,CEDEX/ETH,CENT/BTC,CFT/USDT,CMT/ETH,CMT/USDT,CNN/BTC,CNN/ETH,CNN/USDT,CONI/USDT,COSM/BTC,COSM/ETH,CPC/BTC,CREDO/ETH,CRN/BTC,CSCC/USDT,CS/ETH,CS/USDT,CTXC/ETH,CUST/USDT,CVC/BTC,CXP/BTC,DDAM/ETH,DDAM/USDT,DENT/BTC,DGD/BTC,DSCB/USDT,DTA/ETH,DUC/BTC,DVC/ETH,EBC/BTC,EBC/ETH,EBC/USDT,ECP/BTC,EDC/BTC,EDR/ETH,ELF/BTC,EMT/USDT,EOS/BTC,EOS/USDT,EQUAD/BTC,ETC/BTC,ETC/USDT,ETH/BTC,ETH/USDT,ETK/BTC,FAB/ETH,FCC/BTC,FND/ETH,FNKOS/ETH,FTN/BTC,FTN/USDT,FTT/BTC,FXT/ETH,GDC/BTC,GDC/ETH,GDC/USDT,GETX/ETH,GOM2/USDT,GRAM/USDT,GRN/BTC,GUSD/USDT,GVT/BTC,HAPPY/BTC,HDAC/BTC,HMB/USDT,HNB/USDT,HPT/ETH,HT/USDT,HUP/USDT,INCX/ETH,IOST/BTC,IOTE/USDT,ISR/ETH,IVY/ETH,JOB/BTC,KBC/BTC,KBC/USDT,KMD/BTC,KNT/ETH,KST/BTC,LAMB/USDT,LATX/BTC,LBK/BTC,LINK/BTC,LOOM/BTC,LTC/BTC,LTC/USDT,LUC/ETH,LUX/BTC,LVTC/ETH,MC/USDT,MIB/BTC,MINX/BTC,MINX/ETH,MOAC/USDT,MPL/BTC,MTC/BTC,MT/ETH,MTN/ETH,MT/USDT,MVL/ETH,MXM/ETH,MXM/USDT,MZG/USDT,NANO/BTC,NBAI/ETH,NEO/BTC,NEO/USDT,NFT/USDT,NOBS/BTC,NPXS/ETH,NPXS/USDT,NTY/ETH,ODC/USDT,OMG/BTC,OMX/ETH,OVC/ETH,OZX/ETH,PAT/ETH,PAX/USDT,PLAY/BTC,PMA/ETH,POLL/BTC,POLY/BTC,PPT/BTC,PSM/BTC,QKC/BTC,QTUM/BTC,QTUM/USDT,RBTC/BTC,RCOIN/BTC,RCOIN/USDT,REP/BTC,REV/BTC,RIF/BTC,RRW/USDT,SBT/USDT,SCC/BTC,SCO/BTC,SEN/BTC,SENC/ETH,SHE/BTC,SHVR/BTC,SIM/BTC,SKB/BTC,SKM/ETH,SKYM/USDT,SLT/ETH,SMARTUP/ETH,SMARTUP/USDT,SORO/USDT,SRCOIN/BTC,SRCOIN/ETH,STORJ/BTC,SWET/BTC,SWTC/USDT,TCT/BTC,TEMCO/USDT,TEN/BTC,TEN/ETH,TIB/BTC,TMTG/BTC,TOC/ETH,TOOS/USDT,TOSC/BTC,TRUE/ETH,TRX/BTC,TRX/USDT,TSL/BTC,UNI/USDT,UTNP/BTC,VBT/USDT,VEEN/BTC,VME/BTC,VME/ETH,VSC/ETH,VSF/BTC,W12/BTC,W12/ETH,WBL/BTC,WFX/BTC,XEM/BTC,XLM/BTC,XMCT/ETH,XMCT/USDT,XMR/BTC,XNK/ETH,XRP/BTC,XRP/USDT,XSR/USDT,YAP/BTC,YAP/USDT,YTA/USDT,ZAT/ETH,ZDC/BTC,ZEC/BTC,ZGC/BTC,ZRX/BTC", "requestFormat": { "uppercase": true, diff --git a/testdata/http_mock/binance/binance.json b/testdata/http_mock/binance/binance.json index 1ffe0ce5..4efedede 100644 --- a/testdata/http_mock/binance/binance.json +++ b/testdata/http_mock/binance/binance.json @@ -84596,6 +84596,9013 @@ "queryString": "limit=15\u0026symbol=BTCUSDT", "bodyParams": "", "headers": {} + }, + { + "data": [ + { + "id": 399088278, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00522500", + "quoteQty": "61.00370375", + "time": 1598850897967 + }, + { + "id": 399088279, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.02537300", + "quoteQty": "296.23890928", + "time": 1598850898020 + }, + { + "id": 399088280, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.07425500", + "quoteQty": "866.95385680", + "time": 1598850898020 + }, + { + "id": 399088281, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00774300", + "quoteQty": "90.40223505", + "time": 1598850898072 + }, + { + "id": 399088282, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.02802700", + "quoteQty": "327.22531472", + "time": 1598850898169 + }, + { + "id": 399088283, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.00129000", + "quoteQty": "15.06121440", + "time": 1598850898169 + }, + { + "id": 399088284, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.48000000", + "qty": "0.01365700", + "quoteQty": "159.45203036", + "time": 1598850898169 + }, + { + "id": 399088285, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.59000000", + "qty": "0.14214000", + "quoteQty": "1659.56836260", + "time": 1598850898169 + }, + { + "id": 399088286, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.02419700", + "quoteQty": "282.51473517", + "time": 1598850898169 + }, + { + "id": 399088287, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.49000000", + "qty": "0.00944300", + "quoteQty": "110.25165207", + "time": 1598850898279 + }, + { + "id": 399088288, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.49000000", + "qty": "0.00100300", + "quoteQty": "11.71051647", + "time": 1598850898617 + }, + { + "id": 399088289, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.49000000", + "qty": "0.00321100", + "quoteQty": "37.48999839", + "time": 1598850898765 + }, + { + "id": 399088290, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.49000000", + "qty": "0.00058100", + "quoteQty": "6.78345969", + "time": 1598850898765 + }, + { + "id": 399088291, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.01365700", + "quoteQty": "159.45203036", + "time": 1598850899095 + }, + { + "id": 399088292, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.16923800", + "quoteQty": "1975.93488424", + "time": 1598850899095 + }, + { + "id": 399088293, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.38957200", + "quoteQty": "4548.44009456", + "time": 1598850899163 + }, + { + "id": 399088294, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.03558900", + "quoteQty": "415.51865772", + "time": 1598850899520 + }, + { + "id": 399088295, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.03421200", + "quoteQty": "399.44152176", + "time": 1598850899719 + }, + { + "id": 399088296, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00140300", + "quoteQty": "16.38069844", + "time": 1598850899831 + }, + { + "id": 399088297, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00379100", + "quoteQty": "44.26174468", + "time": 1598850900485 + }, + { + "id": 399088298, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.01347500", + "quoteQty": "157.32709300", + "time": 1598850900485 + }, + { + "id": 399088299, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00019900", + "quoteQty": "2.32342052", + "time": 1598850900991 + }, + { + "id": 399088300, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00357800", + "quoteQty": "41.77486744", + "time": 1598850900991 + }, + { + "id": 399088301, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00021300", + "quoteQty": "2.48687724", + "time": 1598850901166 + }, + { + "id": 399088302, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.41000000", + "qty": "0.00157100", + "quoteQty": "18.34206911", + "time": 1598850901166 + }, + { + "id": 399088303, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00111600", + "quoteQty": "13.02983568", + "time": 1598850901884 + }, + { + "id": 399088304, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00111600", + "quoteQty": "13.02983568", + "time": 1598850902237 + }, + { + "id": 399088305, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.01027100", + "quoteQty": "119.91885508", + "time": 1598850902243 + }, + { + "id": 399088306, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.48000000", + "qty": "0.00114700", + "quoteQty": "13.39177556", + "time": 1598850902251 + }, + { + "id": 399088307, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.38000000", + "qty": "0.00102500", + "quoteQty": "11.96726450", + "time": 1598850902537 + }, + { + "id": 399088308, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.38000000", + "qty": "0.00199400", + "quoteQty": "23.28070772", + "time": 1598850902565 + }, + { + "id": 399088309, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.38000000", + "qty": "0.01658600", + "quoteQty": "193.64785268", + "time": 1598850902798 + }, + { + "id": 399088310, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.38000000", + "qty": "0.00000400", + "quoteQty": "0.04670152", + "time": 1598850902966 + }, + { + "id": 399088311, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00110400", + "quoteQty": "12.88958640", + "time": 1598850902966 + }, + { + "id": 399088312, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00481000", + "quoteQty": "56.15843350", + "time": 1598850903255 + }, + { + "id": 399088313, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.00013900", + "quoteQty": "1.62287365", + "time": 1598850904152 + }, + { + "id": 399088314, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.00448700", + "quoteQty": "52.38729545", + "time": 1598850904152 + }, + { + "id": 399088315, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.34000000", + "qty": "0.00408200", + "quoteQty": "47.65873788", + "time": 1598850904157 + }, + { + "id": 399088316, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.00051300", + "quoteQty": "5.98945455", + "time": 1598850904255 + }, + { + "id": 399088317, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.01798700", + "quoteQty": "210.00452045", + "time": 1598850904255 + }, + { + "id": 399088318, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.00094400", + "quoteQty": "11.02153040", + "time": 1598850904364 + }, + { + "id": 399088319, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.34000000", + "qty": "0.00960400", + "quoteQty": "112.12996536", + "time": 1598850904592 + }, + { + "id": 399088320, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.18000000", + "qty": "0.01366700", + "quoteQty": "159.56468506", + "time": 1598850904661 + }, + { + "id": 399088321, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.02000000", + "qty": "0.00009000", + "quoteQty": "1.05075180", + "time": 1598850904661 + }, + { + "id": 399088322, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.03000000", + "qty": "0.01366700", + "quoteQty": "159.56263501", + "time": 1598850904682 + }, + { + "id": 399088323, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.05000000", + "qty": "0.01371100", + "quoteQty": "160.07661055", + "time": 1598850904712 + }, + { + "id": 399088324, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.01000000", + "qty": "0.00008400", + "quoteQty": "0.98070084", + "time": 1598850904712 + }, + { + "id": 399088325, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.01000000", + "qty": "0.01360700", + "quoteQty": "158.86186107", + "time": 1598850904745 + }, + { + "id": 399088326, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.92000000", + "qty": "0.00010400", + "quoteQty": "1.21419168", + "time": 1598850904745 + }, + { + "id": 399088327, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.91000000", + "qty": "0.01360700", + "quoteQty": "158.86050037", + "time": 1598850904774 + }, + { + "id": 399088328, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.91000000", + "qty": "0.00010200", + "quoteQty": "1.19084082", + "time": 1598850904830 + }, + { + "id": 399088329, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.91000000", + "qty": "0.01351900", + "quoteQty": "157.83310829", + "time": 1598850904830 + }, + { + "id": 399088330, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.92000000", + "qty": "0.00642400", + "quoteQty": "74.99968608", + "time": 1598850904880 + }, + { + "id": 399088331, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.91000000", + "qty": "0.00019400", + "quoteQty": "2.26493254", + "time": 1598850905048 + }, + { + "id": 399088332, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.47000000", + "qty": "0.00715300", + "quoteQty": "83.50748391", + "time": 1598850905048 + }, + { + "id": 399088333, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.34000000", + "qty": "0.00315300", + "quoteQty": "36.80919402", + "time": 1598850905048 + }, + { + "id": 399088334, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.00204000", + "quoteQty": "23.81626560", + "time": 1598850905194 + }, + { + "id": 399088335, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.00840800", + "quoteQty": "98.16028904", + "time": 1598850905435 + }, + { + "id": 399088336, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.00530500", + "quoteQty": "61.93391215", + "time": 1598850905443 + }, + { + "id": 399088337, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.35000000", + "qty": "0.05891000", + "quoteQty": "687.73595850", + "time": 1598850905458 + }, + { + "id": 399088338, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.63000000", + "qty": "0.25467700", + "quoteQty": "2973.25974451", + "time": 1598850905458 + }, + { + "id": 399088339, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.35000000", + "qty": "0.00115100", + "quoteQty": "13.43717685", + "time": 1598850905665 + }, + { + "id": 399088340, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.34000000", + "qty": "0.00503100", + "quoteQty": "58.73360454", + "time": 1598850905794 + }, + { + "id": 399088341, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.34000000", + "qty": "0.00868200", + "quoteQty": "101.35661988", + "time": 1598850906198 + }, + { + "id": 399088342, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.21000000", + "qty": "0.01379100", + "quoteQty": "160.99903011", + "time": 1598850906467 + }, + { + "id": 399088343, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.21000000", + "qty": "0.01193600", + "quoteQty": "139.34337056", + "time": 1598850906467 + }, + { + "id": 399088344, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.00099700", + "quoteQty": "11.63919734", + "time": 1598850906820 + }, + { + "id": 399088345, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.01279400", + "quoteQty": "149.35997068", + "time": 1598850906953 + }, + { + "id": 399088346, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.01237400", + "quoteQty": "144.45679828", + "time": 1598850906953 + }, + { + "id": 399088347, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.03485200", + "quoteQty": "406.86991544", + "time": 1598850906953 + }, + { + "id": 399088348, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.01027800", + "quoteQty": "119.98763316", + "time": 1598850907434 + }, + { + "id": 399088349, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.17992200", + "quoteQty": "2100.44901084", + "time": 1598850908068 + }, + { + "id": 399088350, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.21000000", + "qty": "0.03379900", + "quoteQty": "394.57662379", + "time": 1598850908096 + }, + { + "id": 399088351, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.21000000", + "qty": "0.02651300", + "quoteQty": "309.51832973", + "time": 1598850908162 + }, + { + "id": 399088352, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.05553700", + "quoteQty": "648.35115614", + "time": 1598850908241 + }, + { + "id": 399088353, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.21000000", + "qty": "0.05518100", + "quoteQty": "644.19458201", + "time": 1598850908299 + }, + { + "id": 399088354, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.27196000", + "quoteQty": "3174.92087120", + "time": 1598850908307 + }, + { + "id": 399088355, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.06000100", + "quoteQty": "700.46487422", + "time": 1598850908473 + }, + { + "id": 399088356, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.22000000", + "qty": "0.00595500", + "quoteQty": "69.51998010", + "time": 1598850908481 + }, + { + "id": 399088357, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.34000000", + "qty": "0.00810800", + "quoteQty": "94.65554872", + "time": 1598850909950 + }, + { + "id": 399088358, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.46000000", + "qty": "0.01371300", + "quoteQty": "160.09186998", + "time": 1598850909950 + }, + { + "id": 399088359, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.01167300", + "quoteQty": "136.27807272", + "time": 1598850909950 + }, + { + "id": 399088360, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.85000000", + "qty": "0.00714800", + "quoteQty": "83.45182780", + "time": 1598850909950 + }, + { + "id": 399088361, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.03000000", + "qty": "0.93897000", + "quoteQty": "10962.50291910", + "time": 1598850909950 + }, + { + "id": 399088362, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.03000000", + "qty": "0.00427600", + "quoteQty": "49.92242828", + "time": 1598850909985 + }, + { + "id": 399088363, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.02000000", + "qty": "0.03420300", + "quoteQty": "399.32070906", + "time": 1598850910290 + }, + { + "id": 399088364, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.03000000", + "qty": "0.01379100", + "quoteQty": "161.01033873", + "time": 1598850910810 + }, + { + "id": 399088365, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.03000000", + "qty": "0.03220900", + "quoteQty": "376.04104127", + "time": 1598850910810 + }, + { + "id": 399088366, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.02000000", + "qty": "0.04596700", + "quoteQty": "536.66564434", + "time": 1598850910837 + }, + { + "id": 399088367, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.86000000", + "qty": "0.01122000", + "quoteQty": "130.99192920", + "time": 1598850911267 + }, + { + "id": 399088368, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.85000000", + "qty": "0.01381300", + "quoteQty": "161.26470305", + "time": 1598850911763 + }, + { + "id": 399088369, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.85000000", + "qty": "0.00001300", + "quoteQty": "0.15177305", + "time": 1598850911838 + }, + { + "id": 399088370, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.69000000", + "qty": "0.01384900", + "quoteQty": "161.68278181", + "time": 1598850911838 + }, + { + "id": 399088371, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.68000000", + "qty": "0.01379100", + "quoteQty": "161.00551188", + "time": 1598850911838 + }, + { + "id": 399088372, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.33000000", + "qty": "0.00775100", + "quoteQty": "90.48773183", + "time": 1598850911838 + }, + { + "id": 399088373, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.00359600", + "quoteQty": "41.98067492", + "time": 1598850911838 + }, + { + "id": 399088374, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.01164600", + "quoteQty": "135.96192576", + "time": 1598850911977 + }, + { + "id": 399088375, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00213100", + "quoteQty": "24.87848736", + "time": 1598850912084 + }, + { + "id": 399088376, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00001700", + "quoteQty": "0.19846752", + "time": 1598850912222 + }, + { + "id": 399088377, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.22000000", + "qty": "0.03289200", + "quoteQty": "383.98844424", + "time": 1598850912222 + }, + { + "id": 399088378, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.40000000", + "qty": "0.01376300", + "quoteQty": "160.67476720", + "time": 1598850912260 + }, + { + "id": 399088379, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.40000000", + "qty": "0.06391900", + "quoteQty": "746.21597360", + "time": 1598850912260 + }, + { + "id": 399088380, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.40000000", + "qty": "0.06890500", + "quoteQty": "804.42453200", + "time": 1598850912260 + }, + { + "id": 399088381, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.40000000", + "qty": "0.10000000", + "quoteQty": "1167.44000000", + "time": 1598850912349 + }, + { + "id": 399088382, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.39000000", + "qty": "0.00966800", + "quoteQty": "112.86800252", + "time": 1598850912451 + }, + { + "id": 399088383, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.39000000", + "qty": "0.00409500", + "quoteQty": "47.80662705", + "time": 1598850913067 + }, + { + "id": 399088384, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.22000000", + "qty": "0.04088200", + "quoteQty": "477.26546204", + "time": 1598850913067 + }, + { + "id": 399088385, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.31000000", + "qty": "0.01376300", + "quoteQty": "160.67352853", + "time": 1598850913182 + }, + { + "id": 399088386, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.00349400", + "quoteQty": "40.78986444", + "time": 1598850913182 + }, + { + "id": 399088387, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.04035400", + "quoteQty": "471.10308804", + "time": 1598850913357 + }, + { + "id": 399088388, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.01616000", + "quoteQty": "188.65604160", + "time": 1598850913462 + }, + { + "id": 399088389, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.01399900", + "quoteQty": "163.42796574", + "time": 1598850913495 + }, + { + "id": 399088390, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.04455100", + "quoteQty": "520.09995726", + "time": 1598850913501 + }, + { + "id": 399088391, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.26000000", + "qty": "0.04730200", + "quoteQty": "552.21584652", + "time": 1598850913548 + }, + { + "id": 399088392, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.27000000", + "qty": "0.06004900", + "quoteQty": "701.02823923", + "time": 1598850913847 + }, + { + "id": 399088393, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.27000000", + "qty": "0.04337400", + "quoteQty": "506.35978698", + "time": 1598850913945 + }, + { + "id": 399088394, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.31000000", + "qty": "0.02516200", + "quoteQty": "293.74898822", + "time": 1598850914545 + }, + { + "id": 399088395, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.32000000", + "qty": "0.01376300", + "quoteQty": "160.67366616", + "time": 1598850914759 + }, + { + "id": 399088396, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00387900", + "quoteQty": "45.28565703", + "time": 1598850914944 + }, + { + "id": 399088397, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00991500", + "quoteQty": "115.75336155", + "time": 1598850914946 + }, + { + "id": 399088398, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00362300", + "quoteQty": "42.29696711", + "time": 1598850914946 + }, + { + "id": 399088399, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00816200", + "quoteQty": "95.28775872", + "time": 1598850914989 + }, + { + "id": 399088400, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00096100", + "quoteQty": "11.21926177", + "time": 1598850915012 + }, + { + "id": 399088401, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00922500", + "quoteQty": "107.69790825", + "time": 1598850915553 + }, + { + "id": 399088402, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916020 + }, + { + "id": 399088403, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916020 + }, + { + "id": 399088404, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088405, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088406, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088407, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088408, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088409, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916021 + }, + { + "id": 399088410, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916022 + }, + { + "id": 399088411, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088412, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088413, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088414, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088415, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088416, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088417, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088418, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088419, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088420, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916023 + }, + { + "id": 399088421, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916024 + }, + { + "id": 399088422, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916024 + }, + { + "id": 399088423, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916025 + }, + { + "id": 399088424, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916025 + }, + { + "id": 399088425, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916025 + }, + { + "id": 399088426, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916025 + }, + { + "id": 399088427, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088428, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088429, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088430, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088431, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088432, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088433, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088434, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916026 + }, + { + "id": 399088435, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916027 + }, + { + "id": 399088436, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916027 + }, + { + "id": 399088437, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916027 + }, + { + "id": 399088438, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916027 + }, + { + "id": 399088439, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916027 + }, + { + "id": 399088440, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916028 + }, + { + "id": 399088441, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916028 + }, + { + "id": 399088442, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916028 + }, + { + "id": 399088443, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916029 + }, + { + "id": 399088444, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916030 + }, + { + "id": 399088445, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916034 + }, + { + "id": 399088446, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00669500", + "quoteQty": "78.16124615", + "time": 1598850916036 + }, + { + "id": 399088447, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.01485600", + "quoteQty": "173.43726336", + "time": 1598850916058 + }, + { + "id": 399088448, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.05993900", + "quoteQty": "699.76145184", + "time": 1598850916058 + }, + { + "id": 399088449, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.10228200", + "quoteQty": "1194.09734592", + "time": 1598850916058 + }, + { + "id": 399088450, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.05253000", + "quoteQty": "613.26463680", + "time": 1598850916058 + }, + { + "id": 399088451, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.01138700", + "quoteQty": "132.93821472", + "time": 1598850916085 + }, + { + "id": 399088452, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.02582100", + "quoteQty": "301.44881376", + "time": 1598850916085 + }, + { + "id": 399088453, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.03420700", + "quoteQty": "399.35167392", + "time": 1598850916085 + }, + { + "id": 399088454, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.22912100", + "quoteQty": "2674.88915297", + "time": 1598850916087 + }, + { + "id": 399088455, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.07381400", + "quoteQty": "861.74670998", + "time": 1598850916459 + }, + { + "id": 399088456, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.02061100", + "quoteQty": "240.62435616", + "time": 1598850916810 + }, + { + "id": 399088457, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.02087500", + "quoteQty": "243.70644000", + "time": 1598850917387 + }, + { + "id": 399088458, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.01784300", + "quoteQty": "208.30935251", + "time": 1598850917943 + }, + { + "id": 399088459, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.04393300", + "quoteQty": "512.89844448", + "time": 1598850917954 + }, + { + "id": 399088460, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.02396100", + "quoteQty": "279.73437177", + "time": 1598850917986 + }, + { + "id": 399088461, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00379800", + "quoteQty": "44.33997888", + "time": 1598850918721 + }, + { + "id": 399088462, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00125200", + "quoteQty": "14.61654912", + "time": 1598850918736 + }, + { + "id": 399088463, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.02302600", + "quoteQty": "268.81841856", + "time": 1598850919750 + }, + { + "id": 399088464, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.05109600", + "quoteQty": "596.52382872", + "time": 1598850919801 + }, + { + "id": 399088465, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.02554800", + "quoteQty": "298.26191436", + "time": 1598850919969 + }, + { + "id": 399088466, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.02554800", + "quoteQty": "298.26191436", + "time": 1598850920180 + }, + { + "id": 399088467, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.02554800", + "quoteQty": "298.26191436", + "time": 1598850920292 + }, + { + "id": 399088468, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00459800", + "quoteQty": "53.67962688", + "time": 1598850920299 + }, + { + "id": 399088469, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.01599400", + "quoteQty": "186.72307258", + "time": 1598850920597 + }, + { + "id": 399088470, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.05109600", + "quoteQty": "596.52382872", + "time": 1598850920609 + }, + { + "id": 399088471, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00647700", + "quoteQty": "75.61618989", + "time": 1598850920710 + }, + { + "id": 399088472, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.01259400", + "quoteQty": "147.02953458", + "time": 1598850920821 + }, + { + "id": 399088473, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.08075700", + "quoteQty": "942.80244192", + "time": 1598850921111 + }, + { + "id": 399088474, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.01352800", + "quoteQty": "157.93358296", + "time": 1598850921145 + }, + { + "id": 399088475, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00153300", + "quoteQty": "17.89710048", + "time": 1598850921256 + }, + { + "id": 399088476, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00287900", + "quoteQty": "33.61108703", + "time": 1598850921682 + }, + { + "id": 399088477, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00340700", + "quoteQty": "39.77522592", + "time": 1598850922206 + }, + { + "id": 399088478, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.02230900", + "quoteQty": "260.44798213", + "time": 1598850922310 + }, + { + "id": 399088479, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.12848900", + "quoteQty": "1500.05382473", + "time": 1598850922536 + }, + { + "id": 399088480, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.01606900", + "quoteQty": "187.59850464", + "time": 1598850922673 + }, + { + "id": 399088481, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.01000000", + "quoteQty": "116.74560000", + "time": 1598850922693 + }, + { + "id": 399088482, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.00109900", + "quoteQty": "12.83034144", + "time": 1598850922877 + }, + { + "id": 399088483, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.57000000", + "qty": "0.00100600", + "quoteQty": "11.74461742", + "time": 1598850923237 + }, + { + "id": 399088484, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.56000000", + "qty": "0.02825400", + "quoteQty": "329.85301824", + "time": 1598850924410 + }, + { + "id": 399088485, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.44000000", + "qty": "0.01380500", + "quoteQty": "161.16564420", + "time": 1598850924516 + }, + { + "id": 399088486, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.01307600", + "quoteQty": "152.65510820", + "time": 1598850924577 + }, + { + "id": 399088487, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.44000000", + "qty": "0.00000400", + "quoteQty": "0.04669776", + "time": 1598850925190 + }, + { + "id": 399088488, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.36000000", + "qty": "0.00097100", + "quoteQty": "11.33580356", + "time": 1598850925190 + }, + { + "id": 399088489, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.37000000", + "qty": "0.01490700", + "quoteQty": "174.02983359", + "time": 1598850926050 + }, + { + "id": 399088490, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.37000000", + "qty": "0.03774000", + "quoteQty": "440.59072380", + "time": 1598850926682 + }, + { + "id": 399088491, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.32000000", + "qty": "0.03500000", + "quoteQty": "408.60120000", + "time": 1598850926684 + }, + { + "id": 399088492, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.32000000", + "qty": "0.01667400", + "quoteQty": "194.65761168", + "time": 1598850926723 + }, + { + "id": 399088493, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.00269700", + "quoteQty": "31.48550619", + "time": 1598850927767 + }, + { + "id": 399088494, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00406500", + "quoteQty": "47.45594820", + "time": 1598850928980 + }, + { + "id": 399088495, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.00306700", + "quoteQty": "35.80498609", + "time": 1598850929213 + }, + { + "id": 399088496, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.01512400", + "quoteQty": "176.56165948", + "time": 1598850929213 + }, + { + "id": 399088497, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.03216800", + "quoteQty": "375.53823904", + "time": 1598850929503 + }, + { + "id": 399088498, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00118900", + "quoteQty": "13.88071892", + "time": 1598850929629 + }, + { + "id": 399088499, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00085700", + "quoteQty": "10.00485796", + "time": 1598850929632 + }, + { + "id": 399088500, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.01290100", + "quoteQty": "150.60988628", + "time": 1598850929788 + }, + { + "id": 399088501, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.31296600", + "quoteQty": "3653.65271448", + "time": 1598850929824 + }, + { + "id": 399088502, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00095300", + "quoteQty": "11.12558884", + "time": 1598850930047 + }, + { + "id": 399088503, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00217200", + "quoteQty": "25.35653616", + "time": 1598850930165 + }, + { + "id": 399088504, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.00352000", + "quoteQty": "41.09346560", + "time": 1598850930353 + }, + { + "id": 399088505, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.00685500", + "quoteQty": "80.02712085", + "time": 1598850930910 + }, + { + "id": 399088506, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.01819100", + "quoteQty": "212.36664557", + "time": 1598850931208 + }, + { + "id": 399088507, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.27000000", + "qty": "0.03263000", + "quoteQty": "380.93143010", + "time": 1598850931388 + }, + { + "id": 399088508, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.28000000", + "qty": "0.01154600", + "quoteQty": "134.79123688", + "time": 1598850931404 + }, + { + "id": 399088509, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.02108500", + "quoteQty": "246.15577825", + "time": 1598850931404 + }, + { + "id": 399088510, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.01151800", + "quoteQty": "134.46631510", + "time": 1598850931421 + }, + { + "id": 399088511, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.00095800", + "quoteQty": "11.18412310", + "time": 1598850931427 + }, + { + "id": 399088512, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.44000000", + "qty": "0.03263100", + "quoteQty": "380.94865164", + "time": 1598850931445 + }, + { + "id": 399088513, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.00206700", + "quoteQty": "24.13108815", + "time": 1598850931533 + }, + { + "id": 399088514, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.05174200", + "quoteQty": "604.05939190", + "time": 1598850931728 + }, + { + "id": 399088515, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.02581900", + "quoteQty": "301.42262455", + "time": 1598850931844 + }, + { + "id": 399088516, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.45000000", + "qty": "0.00000200", + "quoteQty": "0.02334890", + "time": 1598850931964 + }, + { + "id": 399088517, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.00614600", + "quoteQty": "71.75233744", + "time": 1598850931964 + }, + { + "id": 399088518, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.05809100", + "quoteQty": "678.19151224", + "time": 1598850932061 + }, + { + "id": 399088519, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.05798700", + "quoteQty": "676.97734968", + "time": 1598850932170 + }, + { + "id": 399088520, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.01000000", + "quoteQty": "116.74630000", + "time": 1598850932312 + }, + { + "id": 399088521, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.02092500", + "quoteQty": "244.29184200", + "time": 1598850932483 + }, + { + "id": 399088522, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.11222300", + "quoteQty": "1310.16312472", + "time": 1598850934346 + }, + { + "id": 399088523, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.00310800", + "quoteQty": "36.28478112", + "time": 1598850936133 + }, + { + "id": 399088524, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.00949200", + "quoteQty": "110.81558796", + "time": 1598850936667 + }, + { + "id": 399088525, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.04821600", + "quoteQty": "562.90396008", + "time": 1598850936693 + }, + { + "id": 399088526, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.05286900", + "quoteQty": "617.22601347", + "time": 1598850936798 + }, + { + "id": 399088527, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.05478300", + "quoteQty": "639.57125529", + "time": 1598850936900 + }, + { + "id": 399088528, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.02152300", + "quoteQty": "251.27327672", + "time": 1598850937220 + }, + { + "id": 399088529, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.01155400", + "quoteQty": "134.88879056", + "time": 1598850937328 + }, + { + "id": 399088530, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.00094200", + "quoteQty": "10.99751088", + "time": 1598850938318 + }, + { + "id": 399088531, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.00759400", + "quoteQty": "88.65714022", + "time": 1598850938326 + }, + { + "id": 399088532, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.63000000", + "qty": "0.02645000", + "quoteQty": "308.79396350", + "time": 1598850938589 + }, + { + "id": 399088533, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.14664000", + "quoteQty": "1711.96920960", + "time": 1598850938703 + }, + { + "id": 399088534, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.01610900", + "quoteQty": "188.06677576", + "time": 1598850939009 + }, + { + "id": 399088535, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.08954800", + "quoteQty": "1045.44066272", + "time": 1598850939016 + }, + { + "id": 399088536, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.08944300", + "quoteQty": "1044.21482552", + "time": 1598850939041 + }, + { + "id": 399088537, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.15351100", + "quoteQty": "1792.18566104", + "time": 1598850939056 + }, + { + "id": 399088538, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.17881500", + "quoteQty": "2087.60075160", + "time": 1598850939056 + }, + { + "id": 399088539, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.03343500", + "quoteQty": "390.34158840", + "time": 1598850939066 + }, + { + "id": 399088540, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.01131900", + "quoteQty": "132.14525016", + "time": 1598850939066 + }, + { + "id": 399088541, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.64000000", + "qty": "0.00251300", + "quoteQty": "29.33837032", + "time": 1598850939066 + }, + { + "id": 399088542, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.86000000", + "qty": "0.00260600", + "quoteQty": "30.42468516", + "time": 1598850939066 + }, + { + "id": 399088543, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.88000000", + "qty": "0.00694400", + "quoteQty": "81.07036672", + "time": 1598850939066 + }, + { + "id": 399088544, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.09000000", + "qty": "0.04200300", + "quoteQty": "490.38880527", + "time": 1598850939066 + }, + { + "id": 399088545, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.11000000", + "qty": "0.01371300", + "quoteQty": "160.10078343", + "time": 1598850939066 + }, + { + "id": 399088546, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.19000000", + "qty": "0.01366700", + "quoteQty": "159.56482173", + "time": 1598850939066 + }, + { + "id": 399088547, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.01000000", + "quoteQty": "116.75350000", + "time": 1598850939066 + }, + { + "id": 399088548, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.49000000", + "qty": "0.01365000", + "quoteQty": "159.37043850", + "time": 1598850939066 + }, + { + "id": 399088549, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.50000000", + "qty": "0.01500000", + "quoteQty": "175.13250000", + "time": 1598850939066 + }, + { + "id": 399088550, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.01367400", + "quoteQty": "159.65160744", + "time": 1598850939066 + }, + { + "id": 399088551, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.57000000", + "qty": "0.00042100", + "quoteQty": "4.91541497", + "time": 1598850939066 + }, + { + "id": 399088552, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.10544700", + "quoteQty": "1231.12430463", + "time": 1598850939224 + }, + { + "id": 399088553, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.00001300", + "quoteQty": "0.15177877", + "time": 1598850939335 + }, + { + "id": 399088554, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.01376500", + "quoteQty": "160.71036685", + "time": 1598850939335 + }, + { + "id": 399088555, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.00003200", + "quoteQty": "0.37360928", + "time": 1598850939407 + }, + { + "id": 399088556, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.01366900", + "quoteQty": "159.58967570", + "time": 1598850939407 + }, + { + "id": 399088557, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.00102300", + "quoteQty": "11.94383190", + "time": 1598850939640 + }, + { + "id": 399088558, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.29000000", + "qty": "0.04662600", + "quoteQty": "544.37207154", + "time": 1598850939789 + }, + { + "id": 399088559, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.29000000", + "qty": "0.03388400", + "quoteQty": "395.60552636", + "time": 1598850939899 + }, + { + "id": 399088560, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.29000000", + "qty": "0.00265700", + "quoteQty": "31.02124553", + "time": 1598850940295 + }, + { + "id": 399088561, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.09068000", + "quoteQty": "1058.71620400", + "time": 1598850940370 + }, + { + "id": 399088562, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.00003100", + "quoteQty": "0.36193430", + "time": 1598850940475 + }, + { + "id": 399088563, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.00197400", + "quoteQty": "23.04704220", + "time": 1598850940475 + }, + { + "id": 399088564, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.30000000", + "qty": "0.00002500", + "quoteQty": "0.29188250", + "time": 1598850940483 + }, + { + "id": 399088565, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.32000000", + "qty": "0.00196800", + "quoteQty": "22.97702976", + "time": 1598850940587 + }, + { + "id": 399088566, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.04774600", + "quoteQty": "557.44935126", + "time": 1598850940761 + }, + { + "id": 399088567, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.01204100", + "quoteQty": "140.58240771", + "time": 1598850940919 + }, + { + "id": 399088568, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.00527900", + "quoteQty": "61.63396149", + "time": 1598850941074 + }, + { + "id": 399088569, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.00199900", + "quoteQty": "23.33894469", + "time": 1598850942265 + }, + { + "id": 399088570, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.02099100", + "quoteQty": "245.07643221", + "time": 1598850942755 + }, + { + "id": 399088571, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.03388400", + "quoteQty": "395.60620404", + "time": 1598850942755 + }, + { + "id": 399088572, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.01869500", + "quoteQty": "218.26992045", + "time": 1598850943212 + }, + { + "id": 399088573, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.00263100", + "quoteQty": "30.71774061", + "time": 1598850943670 + }, + { + "id": 399088574, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.31000000", + "qty": "0.00200000", + "quoteQty": "23.35062000", + "time": 1598850944010 + }, + { + "id": 399088575, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.32000000", + "qty": "0.00003100", + "quoteQty": "0.36193492", + "time": 1598850944639 + }, + { + "id": 399088576, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.01377700", + "quoteQty": "160.85129695", + "time": 1598850944722 + }, + { + "id": 399088577, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.00002000", + "quoteQty": "0.23350700", + "time": 1598850946648 + }, + { + "id": 399088578, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.02869300", + "quoteQty": "335.00827773", + "time": 1598850946745 + }, + { + "id": 399088579, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.01376700", + "quoteQty": "160.73812287", + "time": 1598850946745 + }, + { + "id": 399088580, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.00003000", + "quoteQty": "0.35026830", + "time": 1598850946755 + }, + { + "id": 399088581, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.62000000", + "qty": "0.01366700", + "quoteQty": "159.57069854", + "time": 1598850946900 + }, + { + "id": 399088582, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.62000000", + "qty": "0.00001900", + "quoteQty": "0.22183678", + "time": 1598850947028 + }, + { + "id": 399088583, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.63000000", + "qty": "0.01500000", + "quoteQty": "175.13445000", + "time": 1598850947028 + }, + { + "id": 399088584, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.67000000", + "qty": "0.00000900", + "quoteQty": "0.10508103", + "time": 1598850947028 + }, + { + "id": 399088585, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.67000000", + "qty": "0.01369100", + "quoteQty": "159.85159797", + "time": 1598850947028 + }, + { + "id": 399088586, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.00882800", + "quoteQty": "103.07572800", + "time": 1598850947028 + }, + { + "id": 399088587, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.19000000", + "qty": "0.04651900", + "quoteQty": "543.16468261", + "time": 1598850947028 + }, + { + "id": 399088588, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.20000000", + "qty": "0.04644000", + "quoteQty": "542.24272800", + "time": 1598850947028 + }, + { + "id": 399088589, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.26000000", + "qty": "0.00713700", + "quoteQty": "83.33346762", + "time": 1598850947028 + }, + { + "id": 399088590, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.43000000", + "qty": "0.01349800", + "quoteQty": "157.60845214", + "time": 1598850947028 + }, + { + "id": 399088591, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.55000000", + "qty": "1.84881600", + "quoteQty": "21587.79246480", + "time": 1598850947028 + }, + { + "id": 399088592, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.01367400", + "quoteQty": "159.65871792", + "time": 1598850947135 + }, + { + "id": 399088593, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.05596800", + "quoteQty": "653.48684544", + "time": 1598850947135 + }, + { + "id": 399088594, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.49733500", + "quoteQty": "5806.92324680", + "time": 1598850947169 + }, + { + "id": 399088595, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.28373100", + "quoteQty": "3312.86585448", + "time": 1598850947341 + }, + { + "id": 399088596, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.00763300", + "quoteQty": "89.12351864", + "time": 1598850947496 + }, + { + "id": 399088597, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.09000000", + "qty": "0.01366700", + "quoteQty": "159.57712203", + "time": 1598850947510 + }, + { + "id": 399088598, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.02456600", + "quoteQty": "286.83458128", + "time": 1598850947532 + }, + { + "id": 399088599, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.09000000", + "qty": "0.00000700", + "quoteQty": "0.08173263", + "time": 1598850947793 + }, + { + "id": 399088600, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.09000000", + "qty": "0.05998300", + "quoteQty": "700.36690647", + "time": 1598850947793 + }, + { + "id": 399088601, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.09000000", + "qty": "0.00001700", + "quoteQty": "0.19849353", + "time": 1598850947836 + }, + { + "id": 399088602, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.60000000", + "qty": "0.00100600", + "quoteQty": "11.74665960", + "time": 1598850947836 + }, + { + "id": 399088603, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00758100", + "quoteQty": "88.52022879", + "time": 1598850947897 + }, + { + "id": 399088604, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00864400", + "quoteQty": "100.93244396", + "time": 1598850947983 + }, + { + "id": 399088605, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.01137000", + "quoteQty": "132.76282830", + "time": 1598850948013 + }, + { + "id": 399088606, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00863000", + "quoteQty": "100.76897170", + "time": 1598850948039 + }, + { + "id": 399088607, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00001500", + "quoteQty": "0.17514885", + "time": 1598850948039 + }, + { + "id": 399088608, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00741200", + "quoteQty": "86.54688508", + "time": 1598850948110 + }, + { + "id": 399088609, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00343100", + "quoteQty": "40.06238029", + "time": 1598850948224 + }, + { + "id": 399088610, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.37727900", + "quoteQty": "4405.33219861", + "time": 1598850948228 + }, + { + "id": 399088611, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.59000000", + "qty": "0.00120100", + "quoteQty": "14.02358459", + "time": 1598850948328 + }, + { + "id": 399088612, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.60000000", + "qty": "0.04543000", + "quoteQty": "530.46793800", + "time": 1598850948335 + }, + { + "id": 399088613, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.60000000", + "qty": "0.04282300", + "quoteQty": "500.02704180", + "time": 1598850948509 + }, + { + "id": 399088614, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.37000000", + "qty": "0.02301800", + "quoteQty": "268.76668466", + "time": 1598850948843 + }, + { + "id": 399088615, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.37000000", + "qty": "0.05993900", + "quoteQty": "699.86994143", + "time": 1598850948843 + }, + { + "id": 399088616, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.37000000", + "qty": "0.03449700", + "quoteQty": "402.79973589", + "time": 1598850948843 + }, + { + "id": 399088617, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.37000000", + "qty": "0.03678800", + "quoteQty": "429.55029956", + "time": 1598850948843 + }, + { + "id": 399088618, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.00772500", + "quoteQty": "90.19988100", + "time": 1598850948868 + }, + { + "id": 399088619, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.00445700", + "quoteQty": "52.04153652", + "time": 1598850948868 + }, + { + "id": 399088620, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.00914800", + "quoteQty": "106.81534128", + "time": 1598850949273 + }, + { + "id": 399088621, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.01507300", + "quoteQty": "175.99777428", + "time": 1598850949273 + }, + { + "id": 399088622, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.00639000", + "quoteQty": "74.61194040", + "time": 1598850949291 + }, + { + "id": 399088623, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.00160200", + "quoteQty": "18.70552872", + "time": 1598850949291 + }, + { + "id": 399088624, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.36000000", + "qty": "0.04336100", + "quoteQty": "506.29864596", + "time": 1598850949351 + }, + { + "id": 399088625, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.49000000", + "qty": "0.00260600", + "quoteQty": "30.42893294", + "time": 1598850949675 + }, + { + "id": 399088626, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.00837800", + "quoteQty": "97.82554944", + "time": 1598850950966 + }, + { + "id": 399088627, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.00837800", + "quoteQty": "97.82554944", + "time": 1598850951075 + }, + { + "id": 399088628, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.00365300", + "quoteQty": "42.65418144", + "time": 1598850951171 + }, + { + "id": 399088629, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.00151400", + "quoteQty": "17.67819072", + "time": 1598850951278 + }, + { + "id": 399088630, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.03507000", + "quoteQty": "409.49415360", + "time": 1598850951278 + }, + { + "id": 399088631, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.48000000", + "qty": "0.02194000", + "quoteQty": "256.18197120", + "time": 1598850951288 + }, + { + "id": 399088632, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.01367400", + "quoteQty": "159.66227316", + "time": 1598850951288 + }, + { + "id": 399088633, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.25000000", + "qty": "0.00886700", + "quoteQty": "103.53330875", + "time": 1598850951288 + }, + { + "id": 399088634, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.04161700", + "quoteQty": "485.92508604", + "time": 1598850951288 + }, + { + "id": 399088635, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951288 + }, + { + "id": 399088636, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088637, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088638, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088639, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088640, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088641, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088642, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951289 + }, + { + "id": 399088643, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.08609800", + "quoteQty": "1005.29057976", + "time": 1598850951290 + }, + { + "id": 399088644, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.12000000", + "qty": "0.01863200", + "quoteQty": "217.54946784", + "time": 1598850951290 + }, + { + "id": 399088645, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.11000000", + "qty": "0.06746600", + "quoteQty": "787.74043726", + "time": 1598850951290 + }, + { + "id": 399088646, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.11000000", + "qty": "0.01547600", + "quoteQty": "180.69947836", + "time": 1598850951290 + }, + { + "id": 399088647, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.07062200", + "quoteQty": "824.58812176", + "time": 1598850951290 + }, + { + "id": 399088648, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951290 + }, + { + "id": 399088649, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088650, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088651, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088652, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088653, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088654, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088655, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951291 + }, + { + "id": 399088656, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951292 + }, + { + "id": 399088657, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951292 + }, + { + "id": 399088658, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.09678400", + "quoteQty": "1130.05772672", + "time": 1598850951293 + }, + { + "id": 399088659, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951293 + }, + { + "id": 399088660, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951293 + }, + { + "id": 399088661, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951293 + }, + { + "id": 399088662, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951293 + }, + { + "id": 399088663, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951293 + }, + { + "id": 399088664, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088665, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088666, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088667, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088668, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088669, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.08609800", + "quoteQty": "1005.28713584", + "time": 1598850951295 + }, + { + "id": 399088670, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.02453600", + "quoteQty": "286.48429888", + "time": 1598850951295 + }, + { + "id": 399088671, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.90000000", + "qty": "0.01632000", + "quoteQty": "190.55068800", + "time": 1598850951295 + }, + { + "id": 399088672, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.62000000", + "qty": "0.04524200", + "quoteQty": "528.22840004", + "time": 1598850951295 + }, + { + "id": 399088673, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.62000000", + "qty": "0.05710800", + "quoteQty": "666.77130696", + "time": 1598850951295 + }, + { + "id": 399088674, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.61000000", + "qty": "0.02899000", + "quoteQty": "338.47593390", + "time": 1598850951295 + }, + { + "id": 399088675, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.61000000", + "qty": "0.07326200", + "quoteQty": "855.37853982", + "time": 1598850951295 + }, + { + "id": 399088676, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.47000000", + "qty": "0.01283600", + "quoteQty": "149.86633292", + "time": 1598850951295 + }, + { + "id": 399088677, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.47000000", + "qty": "0.00096100", + "quoteQty": "11.22012667", + "time": 1598850951295 + }, + { + "id": 399088678, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.30000000", + "qty": "0.02509400", + "quoteQty": "292.97997820", + "time": 1598850951295 + }, + { + "id": 399088679, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.22000000", + "qty": "0.01379700", + "quoteQty": "161.08301034", + "time": 1598850951295 + }, + { + "id": 399088680, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.10000000", + "qty": "0.01379700", + "quoteQty": "161.08135470", + "time": 1598850951295 + }, + { + "id": 399088681, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.94000000", + "qty": "0.03244900", + "quoteQty": "378.84012806", + "time": 1598850951295 + }, + { + "id": 399088682, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.94000000", + "qty": "0.08192000", + "quoteQty": "956.41108480", + "time": 1598850951295 + }, + { + "id": 399088683, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.93000000", + "qty": "0.00417800", + "quoteQty": "48.77785754", + "time": 1598850951295 + }, + { + "id": 399088684, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.93000000", + "qty": "0.08609800", + "quoteQty": "1005.18812314", + "time": 1598850951295 + }, + { + "id": 399088685, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.93000000", + "qty": "0.02400300", + "quoteQty": "280.23334479", + "time": 1598850951296 + }, + { + "id": 399088686, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.88000000", + "qty": "0.06209500", + "quoteQty": "724.95167360", + "time": 1598850951296 + }, + { + "id": 399088687, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.88000000", + "qty": "0.08609800", + "quoteQty": "1005.18381824", + "time": 1598850951296 + }, + { + "id": 399088688, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.88000000", + "qty": "0.08609800", + "quoteQty": "1005.18381824", + "time": 1598850951296 + }, + { + "id": 399088689, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.88000000", + "qty": "0.08609800", + "quoteQty": "1005.18381824", + "time": 1598850951296 + }, + { + "id": 399088690, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.88000000", + "qty": "0.03883400", + "quoteQty": "453.38228992", + "time": 1598850951296 + }, + { + "id": 399088691, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.85000000", + "qty": "0.04726400", + "quoteQty": "551.80011040", + "time": 1598850951296 + }, + { + "id": 399088692, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.35000000", + "qty": "0.01371600", + "quoteQty": "160.15281660", + "time": 1598850951311 + }, + { + "id": 399088693, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.30000000", + "qty": "0.01360500", + "quoteQty": "158.85606150", + "time": 1598850951311 + }, + { + "id": 399088694, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.85000000", + "qty": "0.08609800", + "quoteQty": "1005.18123530", + "time": 1598850951324 + }, + { + "id": 399088695, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.12000000", + "qty": "0.84840300", + "quoteQty": "9906.05523636", + "time": 1598850951354 + }, + { + "id": 399088696, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.13000000", + "qty": "0.00890400", + "quoteQty": "103.96426152", + "time": 1598850951354 + }, + { + "id": 399088697, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.13000000", + "qty": "0.01360500", + "quoteQty": "158.85374865", + "time": 1598850951354 + }, + { + "id": 399088698, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.42717400", + "quoteQty": "4987.83313490", + "time": 1598850951354 + }, + { + "id": 399088699, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.08000000", + "qty": "0.00400200", + "quoteQty": "46.72767216", + "time": 1598850951365 + }, + { + "id": 399088700, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.01361900", + "quoteQty": "159.01013259", + "time": 1598850951480 + }, + { + "id": 399088701, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.01214800", + "quoteQty": "141.83531028", + "time": 1598850951480 + }, + { + "id": 399088702, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.01358900", + "quoteQty": "158.65972840", + "time": 1598850951486 + }, + { + "id": 399088703, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.00003000", + "quoteQty": "0.35026800", + "time": 1598850951595 + }, + { + "id": 399088704, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.09248300", + "quoteQty": "1079.79451480", + "time": 1598850951595 + }, + { + "id": 399088705, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.71000000", + "qty": "0.00141500", + "quoteQty": "16.52112965", + "time": 1598850953298 + }, + { + "id": 399088706, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.72000000", + "qty": "0.01361900", + "quoteQty": "159.01163068", + "time": 1598850953486 + }, + { + "id": 399088707, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.83000000", + "qty": "0.01361900", + "quoteQty": "159.01312877", + "time": 1598850953486 + }, + { + "id": 399088708, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.95000000", + "qty": "0.00768000", + "quoteQty": "89.67129600", + "time": 1598850953486 + }, + { + "id": 399088709, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.03000000", + "qty": "0.04215900", + "quoteQty": "492.24974877", + "time": 1598850953486 + }, + { + "id": 399088710, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.10000000", + "qty": "0.05377700", + "quoteQty": "627.90562970", + "time": 1598850953602 + }, + { + "id": 399088711, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.10000000", + "qty": "0.02915200", + "quoteQty": "340.38166720", + "time": 1598850954002 + }, + { + "id": 399088712, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.11000000", + "qty": "0.00101900", + "quoteQty": "11.89795609", + "time": 1598850954060 + }, + { + "id": 399088713, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.10000000", + "qty": "0.05227600", + "quoteQty": "610.37980360", + "time": 1598850955629 + }, + { + "id": 399088714, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.10000000", + "qty": "0.25670300", + "quoteQty": "2997.28989830", + "time": 1598850956472 + }, + { + "id": 399088715, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.02448300", + "quoteQty": "285.86057004", + "time": 1598850957535 + }, + { + "id": 399088716, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.04516700", + "quoteQty": "527.36447196", + "time": 1598850957630 + }, + { + "id": 399088717, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.03260200", + "quoteQty": "380.65703976", + "time": 1598850957728 + }, + { + "id": 399088718, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.01570300", + "quoteQty": "183.34634364", + "time": 1598850957728 + }, + { + "id": 399088719, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.00622000", + "quoteQty": "72.62397360", + "time": 1598850958800 + }, + { + "id": 399088720, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.05701000", + "quoteQty": "665.64191880", + "time": 1598850958800 + }, + { + "id": 399088721, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.10072700", + "quoteQty": "1176.07636476", + "time": 1598850958800 + }, + { + "id": 399088722, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.88000000", + "qty": "0.04390000", + "quoteQty": "512.57113200", + "time": 1598850958898 + }, + { + "id": 399088723, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.01368800", + "quoteQty": "159.82108800", + "time": 1598850958898 + }, + { + "id": 399088724, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.11000000", + "qty": "0.01260000", + "quoteQty": "147.11898600", + "time": 1598850958898 + }, + { + "id": 399088725, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.20000000", + "qty": "0.05469300", + "quoteQty": "638.60640660", + "time": 1598850958898 + }, + { + "id": 399088726, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.28000000", + "qty": "0.00820000", + "quoteQty": "95.74549600", + "time": 1598850958898 + }, + { + "id": 399088727, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.46000000", + "qty": "0.01800700", + "quoteQty": "210.25801522", + "time": 1598850958898 + }, + { + "id": 399088728, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.48000000", + "qty": "0.04631600", + "quoteQty": "540.80784768", + "time": 1598850958898 + }, + { + "id": 399088729, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.49000000", + "qty": "0.01099900", + "quoteQty": "128.42971351", + "time": 1598850958898 + }, + { + "id": 399088730, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.50000000", + "qty": "0.01500000", + "quoteQty": "175.14750000", + "time": 1598850958898 + }, + { + "id": 399088731, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.58000000", + "qty": "0.03160000", + "quoteQty": "368.97992800", + "time": 1598850958898 + }, + { + "id": 399088732, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.19000000", + "qty": "0.01365400", + "quoteQty": "159.42669826", + "time": 1598850960276 + }, + { + "id": 399088733, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.18000000", + "qty": "0.01365400", + "quoteQty": "159.42656172", + "time": 1598850960307 + }, + { + "id": 399088734, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.18000000", + "qty": "0.01214900", + "quoteQty": "141.85391082", + "time": 1598850960307 + }, + { + "id": 399088735, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.18000000", + "qty": "0.07928600", + "quoteQty": "925.75760748", + "time": 1598850960307 + }, + { + "id": 399088736, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.18000000", + "qty": "0.17754600", + "quoteQty": "2073.05905428", + "time": 1598850961049 + }, + { + "id": 399088737, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.18000000", + "qty": "0.01214900", + "quoteQty": "141.85391082", + "time": 1598850961049 + }, + { + "id": 399088738, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.10000000", + "qty": "0.01214900", + "quoteQty": "141.85293890", + "time": 1598850961049 + }, + { + "id": 399088739, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.06000000", + "qty": "0.73607900", + "quoteQty": "8594.50256874", + "time": 1598850961049 + }, + { + "id": 399088740, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.07000000", + "qty": "0.02199300", + "quoteQty": "256.79180751", + "time": 1598850961068 + }, + { + "id": 399088741, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.06000000", + "qty": "0.02505600", + "quoteQty": "292.55535936", + "time": 1598850961141 + }, + { + "id": 399088742, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.07000000", + "qty": "0.00098000", + "quoteQty": "11.44254860", + "time": 1598850962266 + }, + { + "id": 399088743, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.13000000", + "qty": "0.00802800", + "quoteQty": "93.73597164", + "time": 1598850962931 + }, + { + "id": 399088744, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.13000000", + "qty": "0.00562600", + "quoteQty": "65.68990738", + "time": 1598850962931 + }, + { + "id": 399088745, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.22000000", + "qty": "0.00240200", + "quoteQty": "28.04628044", + "time": 1598850962931 + }, + { + "id": 399088746, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.22000000", + "qty": "0.00802800", + "quoteQty": "93.73669416", + "time": 1598850962931 + }, + { + "id": 399088747, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.22000000", + "qty": "0.00322900", + "quoteQty": "37.70251438", + "time": 1598850962931 + }, + { + "id": 399088748, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.23000000", + "qty": "0.00479900", + "quoteQty": "56.03422777", + "time": 1598850962931 + }, + { + "id": 399088749, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.23000000", + "qty": "0.00802800", + "quoteQty": "93.73677444", + "time": 1598850962931 + }, + { + "id": 399088750, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.23000000", + "qty": "0.00082700", + "quoteQty": "9.65624221", + "time": 1598850962931 + }, + { + "id": 399088751, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00720100", + "quoteQty": "84.08132434", + "time": 1598850962931 + }, + { + "id": 399088752, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088753, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088754, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088755, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088756, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088757, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088758, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962932 + }, + { + "id": 399088759, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962933 + }, + { + "id": 399088760, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962933 + }, + { + "id": 399088761, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962933 + }, + { + "id": 399088762, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962933 + }, + { + "id": 399088763, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088764, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088765, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088766, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088767, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088768, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962934 + }, + { + "id": 399088769, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962935 + }, + { + "id": 399088770, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962935 + }, + { + "id": 399088771, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088772, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088773, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088774, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088775, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088776, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088777, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088778, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088779, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962936 + }, + { + "id": 399088780, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962938 + }, + { + "id": 399088781, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962938 + }, + { + "id": 399088782, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962938 + }, + { + "id": 399088783, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962938 + }, + { + "id": 399088784, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962939 + }, + { + "id": 399088785, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962939 + }, + { + "id": 399088786, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962939 + }, + { + "id": 399088787, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962939 + }, + { + "id": 399088788, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962940 + }, + { + "id": 399088789, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962940 + }, + { + "id": 399088790, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.00802800", + "quoteQty": "93.73765752", + "time": 1598850962944 + }, + { + "id": 399088791, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.15000000", + "qty": "0.01362500", + "quoteQty": "159.08754375", + "time": 1598850962967 + }, + { + "id": 399088792, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.08000000", + "qty": "0.02582400", + "quoteQty": "301.52308992", + "time": 1598850962967 + }, + { + "id": 399088793, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.01214900", + "quoteQty": "141.85233145", + "time": 1598850962967 + }, + { + "id": 399088794, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.01365400", + "quoteQty": "159.42478670", + "time": 1598850962967 + }, + { + "id": 399088795, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.02000000", + "qty": "0.26011800", + "quoteQty": "3037.14297036", + "time": 1598850962967 + }, + { + "id": 399088796, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.16000000", + "qty": "0.00872800", + "quoteQty": "101.90952448", + "time": 1598850962979 + }, + { + "id": 399088797, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.03000000", + "qty": "0.01366000", + "quoteQty": "159.49456980", + "time": 1598850962982 + }, + { + "id": 399088798, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.16000000", + "qty": "0.00489700", + "quoteQty": "57.17815552", + "time": 1598850962982 + }, + { + "id": 399088799, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.36056000", + "quoteQty": "4210.02475600", + "time": 1598850963010 + }, + { + "id": 399088800, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "3.00000000", + "quoteQty": "35029.02000000", + "time": 1598850963197 + }, + { + "id": 399088801, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.01603100", + "quoteQty": "187.18340654", + "time": 1598850963205 + }, + { + "id": 399088802, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.02481100", + "quoteQty": "289.70167174", + "time": 1598850963306 + }, + { + "id": 399088803, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.02582400", + "quoteQty": "301.52980416", + "time": 1598850963493 + }, + { + "id": 399088804, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.00678500", + "quoteQty": "79.22403475", + "time": 1598850963795 + }, + { + "id": 399088805, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.03312200", + "quoteQty": "386.74373348", + "time": 1598850963899 + }, + { + "id": 399088806, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.63265500", + "quoteQty": "7387.10120925", + "time": 1598850963947 + }, + { + "id": 399088807, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "2.38204000", + "quoteQty": "27813.53275400", + "time": 1598850963947 + }, + { + "id": 399088808, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.00001300", + "quoteQty": "0.15179242", + "time": 1598850964111 + }, + { + "id": 399088809, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.33904100", + "quoteQty": "3958.75798994", + "time": 1598850964111 + }, + { + "id": 399088810, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.49165500", + "quoteQty": "5740.73094270", + "time": 1598850964211 + }, + { + "id": 399088811, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.55248800", + "quoteQty": "6451.04325880", + "time": 1598850964291 + }, + { + "id": 399088812, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.16893000", + "quoteQty": "1972.48411620", + "time": 1598850964310 + }, + { + "id": 399088813, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.01074900", + "quoteQty": "125.50897866", + "time": 1598850964315 + }, + { + "id": 399088814, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.04325400", + "quoteQty": "505.04884290", + "time": 1598850965177 + }, + { + "id": 399088815, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.12697500", + "quoteQty": "1482.60327150", + "time": 1598850965178 + }, + { + "id": 399088816, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.01757800", + "quoteQty": "205.24688030", + "time": 1598850965277 + }, + { + "id": 399088817, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.06563600", + "quoteQty": "766.38825224", + "time": 1598850965592 + }, + { + "id": 399088818, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.01814100", + "quoteQty": "211.82048394", + "time": 1598850965699 + }, + { + "id": 399088819, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.35000000", + "qty": "0.00375600", + "quoteQty": "43.85637060", + "time": 1598850965937 + }, + { + "id": 399088820, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.34000000", + "qty": "0.00000100", + "quoteQty": "0.01167634", + "time": 1598850965970 + }, + { + "id": 399088821, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.33000000", + "qty": "0.08372500", + "quoteQty": "977.60072925", + "time": 1598850965970 + }, + { + "id": 399088822, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.11000000", + "qty": "0.00654300", + "quoteQty": "76.39678773", + "time": 1598850965970 + }, + { + "id": 399088823, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.04000000", + "qty": "0.11809600", + "quoteQty": "1378.89361984", + "time": 1598850965970 + }, + { + "id": 399088824, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.03621600", + "quoteQty": "422.85765384", + "time": 1598850965970 + }, + { + "id": 399088825, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.08183300", + "quoteQty": "955.48128967", + "time": 1598850965970 + }, + { + "id": 399088826, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.92000000", + "qty": "0.00675400", + "quoteQty": "78.85916368", + "time": 1598850965970 + }, + { + "id": 399088827, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.02198400", + "quoteQty": "256.68628320", + "time": 1598850965980 + }, + { + "id": 399088828, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.93000000", + "qty": "0.01855700", + "quoteQty": "216.67023301", + "time": 1598850965983 + }, + { + "id": 399088829, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00104800", + "quoteQty": "12.23643752", + "time": 1598850966013 + }, + { + "id": 399088830, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00118700", + "quoteQty": "13.85940013", + "time": 1598850966192 + }, + { + "id": 399088831, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.02554800", + "quoteQty": "298.29844800", + "time": 1598850966434 + }, + { + "id": 399088832, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.05062300", + "quoteQty": "591.07414800", + "time": 1598850966850 + }, + { + "id": 399088833, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.04603500", + "quoteQty": "537.50466000", + "time": 1598850966963 + }, + { + "id": 399088834, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.04771500", + "quoteQty": "557.12034000", + "time": 1598850967062 + }, + { + "id": 399088835, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.00603800", + "quoteQty": "70.49968800", + "time": 1598850967062 + }, + { + "id": 399088836, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.01088100", + "quoteQty": "127.04655600", + "time": 1598850967165 + }, + { + "id": 399088837, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.01139000", + "quoteQty": "132.98952610", + "time": 1598850967965 + }, + { + "id": 399088838, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.88000000", + "qty": "0.02739300", + "quoteQty": "319.83738084", + "time": 1598850967965 + }, + { + "id": 399088839, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.87000000", + "qty": "0.01361900", + "quoteQty": "159.01367353", + "time": 1598850967965 + }, + { + "id": 399088840, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.87000000", + "qty": "0.01368800", + "quoteQty": "159.81930856", + "time": 1598850967965 + }, + { + "id": 399088841, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.76000000", + "qty": "0.00839400", + "quoteQty": "98.00632944", + "time": 1598850967965 + }, + { + "id": 399088842, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.71000000", + "qty": "0.01220400", + "quoteQty": "142.49036484", + "time": 1598850967965 + }, + { + "id": 399088843, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.61000000", + "qty": "0.14784100", + "quoteQty": "1726.13385801", + "time": 1598850967965 + }, + { + "id": 399088844, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.01361900", + "quoteQty": "159.00999640", + "time": 1598850967965 + }, + { + "id": 399088845, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.08501800", + "quoteQty": "992.63616080", + "time": 1598850967965 + }, + { + "id": 399088846, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.00106300", + "quoteQty": "12.41117343", + "time": 1598850968235 + }, + { + "id": 399088847, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.10000000", + "quoteQty": "1167.56100000", + "time": 1598850968843 + }, + { + "id": 399088848, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.04913000", + "quoteQty": "573.62222800", + "time": 1598850968970 + }, + { + "id": 399088849, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.01360800", + "quoteQty": "158.88156480", + "time": 1598850968970 + }, + { + "id": 399088850, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.20584000", + "quoteQty": "2403.30550400", + "time": 1598850968970 + }, + { + "id": 399088851, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.00095000", + "quoteQty": "11.09182950", + "time": 1598850970460 + }, + { + "id": 399088852, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.00156700", + "quoteQty": "18.29566520", + "time": 1598850970498 + }, + { + "id": 399088853, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.00983700", + "quoteQty": "114.85287720", + "time": 1598850970607 + }, + { + "id": 399088854, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.10908400", + "quoteQty": "1273.62115040", + "time": 1598850970709 + }, + { + "id": 399088855, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.61000000", + "qty": "0.00130300", + "quoteQty": "15.21331983", + "time": 1598850970793 + }, + { + "id": 399088856, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.60000000", + "qty": "0.01271100", + "quoteQty": "148.40855160", + "time": 1598850970874 + }, + { + "id": 399088857, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.69000000", + "qty": "0.00100000", + "quoteQty": "11.67569000", + "time": 1598850971156 + }, + { + "id": 399088858, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.70000000", + "qty": "0.01361000", + "quoteQty": "158.90627700", + "time": 1598850971535 + }, + { + "id": 399088859, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.70000000", + "qty": "0.01208500", + "quoteQty": "141.10083450", + "time": 1598850971535 + }, + { + "id": 399088860, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.78000000", + "qty": "0.01366500", + "quoteQty": "159.54953370", + "time": 1598850971937 + }, + { + "id": 399088861, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.79000000", + "qty": "0.01360800", + "quoteQty": "158.88415032", + "time": 1598850971937 + }, + { + "id": 399088862, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.01000000", + "qty": "0.09272700", + "quoteQty": "1082.68137927", + "time": 1598850971937 + }, + { + "id": 399088863, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.01370800", + "quoteQty": "160.05268888", + "time": 1598850974312 + }, + { + "id": 399088864, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.00870700", + "quoteQty": "101.66171302", + "time": 1598850974312 + }, + { + "id": 399088865, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.04545200", + "quoteQty": "530.69118872", + "time": 1598850974312 + }, + { + "id": 399088866, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.04590200", + "quoteQty": "535.94532572", + "time": 1598850974336 + }, + { + "id": 399088867, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.95000000", + "qty": "0.01370900", + "quoteQty": "160.06559855", + "time": 1598850974410 + }, + { + "id": 399088868, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.03621400", + "quoteQty": "422.82959404", + "time": 1598850974439 + }, + { + "id": 399088869, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.03191000", + "quoteQty": "372.57669260", + "time": 1598850974535 + }, + { + "id": 399088870, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.01690600", + "quoteQty": "197.39208916", + "time": 1598850974535 + }, + { + "id": 399088871, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.05126200", + "quoteQty": "598.52793532", + "time": 1598850974641 + }, + { + "id": 399088872, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.01555400", + "quoteQty": "181.60632644", + "time": 1598850974752 + }, + { + "id": 399088873, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.85000000", + "qty": "0.00216400", + "quoteQty": "25.26653940", + "time": 1598850974960 + }, + { + "id": 399088874, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.85000000", + "qty": "0.01154400", + "quoteQty": "134.78601240", + "time": 1598850975266 + }, + { + "id": 399088875, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.85000000", + "qty": "0.02455400", + "quoteQty": "286.68882090", + "time": 1598850975266 + }, + { + "id": 399088876, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.85000000", + "qty": "0.00755300", + "quoteQty": "88.18769505", + "time": 1598850975348 + }, + { + "id": 399088877, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.86000000", + "qty": "0.00000300", + "quoteQty": "0.03502758", + "time": 1598850975515 + }, + { + "id": 399088878, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.95000000", + "qty": "0.00855500", + "quoteQty": "99.88775225", + "time": 1598850975515 + }, + { + "id": 399088879, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.01370800", + "quoteQty": "160.05282596", + "time": 1598850975587 + }, + { + "id": 399088880, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04977000", + "quoteQty": "581.10804990", + "time": 1598850975760 + }, + { + "id": 399088881, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.86000000", + "qty": "0.06288100", + "quoteQty": "734.18975266", + "time": 1598850975899 + }, + { + "id": 399088882, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04923300", + "quoteQty": "574.83810771", + "time": 1598850975910 + }, + { + "id": 399088883, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04511800", + "quoteQty": "526.79190266", + "time": 1598850976015 + }, + { + "id": 399088884, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05397900", + "quoteQty": "630.25178673", + "time": 1598850976107 + }, + { + "id": 399088885, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05436500", + "quoteQty": "634.75867255", + "time": 1598850976214 + }, + { + "id": 399088886, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05307500", + "quoteQty": "619.69680025", + "time": 1598850976319 + }, + { + "id": 399088887, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05286700", + "quoteQty": "617.26821929", + "time": 1598850976441 + }, + { + "id": 399088888, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04722900", + "quoteQty": "551.43966423", + "time": 1598850976561 + }, + { + "id": 399088889, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05066100", + "quoteQty": "591.51125007", + "time": 1598850976648 + }, + { + "id": 399088890, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04513700", + "quoteQty": "527.01374419", + "time": 1598850976750 + }, + { + "id": 399088891, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.05249400", + "quoteQty": "612.91311978", + "time": 1598850976852 + }, + { + "id": 399088892, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.04579500", + "quoteQty": "534.69646665", + "time": 1598850976953 + }, + { + "id": 399088893, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.87000000", + "qty": "0.00027700", + "quoteQty": "3.23421599", + "time": 1598850976970 + }, + { + "id": 399088894, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.95000000", + "qty": "0.01379300", + "quoteQty": "161.04637835", + "time": 1598850976970 + }, + { + "id": 399088895, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.96000000", + "qty": "0.01370800", + "quoteQty": "160.05405968", + "time": 1598850977051 + }, + { + "id": 399088896, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.95000000", + "qty": "0.00114200", + "quoteQty": "13.33393490", + "time": 1598850977547 + }, + { + "id": 399088897, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.96000000", + "qty": "0.00000100", + "quoteQty": "0.01167596", + "time": 1598850978679 + }, + { + "id": 399088898, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.05000000", + "qty": "0.00103000", + "quoteQty": "12.02633150", + "time": 1598850978679 + }, + { + "id": 399088899, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.04000000", + "qty": "0.03728400", + "quoteQty": "435.32947536", + "time": 1598850978692 + }, + { + "id": 399088900, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.06000000", + "qty": "0.00429600", + "quoteQty": "50.16035376", + "time": 1598850979096 + }, + { + "id": 399088901, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.00256900", + "quoteQty": "29.99577245", + "time": 1598850979259 + }, + { + "id": 399088902, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.00814200", + "quoteQty": "95.06639910", + "time": 1598850979293 + }, + { + "id": 399088903, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.00807900", + "quoteQty": "94.33080795", + "time": 1598850979297 + }, + { + "id": 399088904, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.18721400", + "quoteQty": "2185.92002470", + "time": 1598850980055 + }, + { + "id": 399088905, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.21850800", + "quoteQty": "2551.31033340", + "time": 1598850980155 + }, + { + "id": 399088906, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.07999500", + "quoteQty": "934.02561975", + "time": 1598850980258 + }, + { + "id": 399088907, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.06691400", + "quoteQty": "781.29120970", + "time": 1598850980369 + }, + { + "id": 399088908, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.06000000", + "qty": "0.00199800", + "quoteQty": "23.32876788", + "time": 1598850981192 + }, + { + "id": 399088909, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.05000000", + "qty": "0.00000400", + "quoteQty": "0.04670420", + "time": 1598850981206 + }, + { + "id": 399088910, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.04000000", + "qty": "0.00092700", + "quoteQty": "10.82368908", + "time": 1598850981206 + }, + { + "id": 399088911, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.04000000", + "qty": "0.06407100", + "quoteQty": "748.09555884", + "time": 1598850981297 + }, + { + "id": 399088912, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.04000000", + "qty": "0.00178700", + "quoteQty": "20.86508348", + "time": 1598850981297 + }, + { + "id": 399088913, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.05000000", + "qty": "0.00852800", + "quoteQty": "99.57335440", + "time": 1598850982748 + }, + { + "id": 399088914, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.04000000", + "qty": "0.00002400", + "quoteQty": "0.28022496", + "time": 1598850982827 + }, + { + "id": 399088915, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.96000000", + "qty": "0.01488100", + "quoteQty": "173.74996076", + "time": 1598850982827 + }, + { + "id": 399088916, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.97000000", + "qty": "0.03216400", + "quoteQty": "375.54589908", + "time": 1598850982929 + }, + { + "id": 399088917, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.97000000", + "qty": "0.00000100", + "quoteQty": "0.01167597", + "time": 1598850982937 + }, + { + "id": 399088918, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.95000000", + "qty": "0.06625100", + "quoteQty": "773.54336345", + "time": 1598850982999 + }, + { + "id": 399088919, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.95000000", + "qty": "0.06204200", + "quoteQty": "724.39928990", + "time": 1598850982999 + }, + { + "id": 399088920, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.95000000", + "qty": "0.00002400", + "quoteQty": "0.28022280", + "time": 1598850984149 + }, + { + "id": 399088921, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.73000000", + "qty": "0.01964500", + "quoteQty": "229.36971585", + "time": 1598850984149 + }, + { + "id": 399088922, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.69000000", + "qty": "0.01261000", + "quoteQty": "147.23045090", + "time": 1598850984149 + }, + { + "id": 399088923, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.43000000", + "qty": "0.00667800", + "quoteQty": "77.96852154", + "time": 1598850984149 + }, + { + "id": 399088924, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01366000", + "quoteQty": "159.48801300", + "time": 1598850984270 + }, + { + "id": 399088925, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985104 + }, + { + "id": 399088926, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985104 + }, + { + "id": 399088927, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088928, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088929, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088930, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00065500", + "quoteQty": "7.64749180", + "time": 1598850985105 + }, + { + "id": 399088931, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00194900", + "quoteQty": "22.75566644", + "time": 1598850985105 + }, + { + "id": 399088932, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088933, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088934, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985105 + }, + { + "id": 399088935, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985106 + }, + { + "id": 399088936, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985106 + }, + { + "id": 399088937, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088938, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088939, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088940, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088941, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088942, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985107 + }, + { + "id": 399088943, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985108 + }, + { + "id": 399088944, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985108 + }, + { + "id": 399088945, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985108 + }, + { + "id": 399088946, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985109 + }, + { + "id": 399088947, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985109 + }, + { + "id": 399088948, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985109 + }, + { + "id": 399088949, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985110 + }, + { + "id": 399088950, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985110 + }, + { + "id": 399088951, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985111 + }, + { + "id": 399088952, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985111 + }, + { + "id": 399088953, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985111 + }, + { + "id": 399088954, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985112 + }, + { + "id": 399088955, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985112 + }, + { + "id": 399088956, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985112 + }, + { + "id": 399088957, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985112 + }, + { + "id": 399088958, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985112 + }, + { + "id": 399088959, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985114 + }, + { + "id": 399088960, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00260400", + "quoteQty": "30.40315824", + "time": 1598850985116 + }, + { + "id": 399088961, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00001500", + "quoteQty": "0.17513325", + "time": 1598850985127 + }, + { + "id": 399088962, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.09091300", + "quoteQty": "1061.45927715", + "time": 1598850985127 + }, + { + "id": 399088963, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.47909300", + "quoteQty": "5593.67427615", + "time": 1598850985158 + }, + { + "id": 399088964, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.09079900", + "quoteQty": "1060.12917244", + "time": 1598850985183 + }, + { + "id": 399088965, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00244000", + "quoteQty": "28.48834200", + "time": 1598850985309 + }, + { + "id": 399088966, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.01238200", + "quoteQty": "144.56678392", + "time": 1598850985727 + }, + { + "id": 399088967, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.04300000", + "quoteQty": "502.04865000", + "time": 1598850985833 + }, + { + "id": 399088968, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00100100", + "quoteQty": "11.68723556", + "time": 1598850986878 + }, + { + "id": 399088969, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.00863800", + "quoteQty": "100.85348728", + "time": 1598850986881 + }, + { + "id": 399088970, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.02355300", + "quoteQty": "274.99446468", + "time": 1598850986969 + }, + { + "id": 399088971, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987435 + }, + { + "id": 399088972, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987435 + }, + { + "id": 399088973, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088974, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088975, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088976, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088977, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088978, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088979, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987436 + }, + { + "id": 399088980, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987437 + }, + { + "id": 399088981, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987437 + }, + { + "id": 399088982, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987437 + }, + { + "id": 399088983, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987437 + }, + { + "id": 399088984, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987439 + }, + { + "id": 399088985, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088986, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088987, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088988, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088989, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088990, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088991, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987440 + }, + { + "id": 399088992, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088993, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088994, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088995, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088996, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088997, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088998, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987441 + }, + { + "id": 399088999, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987442 + }, + { + "id": 399089000, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987442 + }, + { + "id": 399089001, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089002, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089003, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089004, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089005, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089006, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089007, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987443 + }, + { + "id": 399089008, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987444 + }, + { + "id": 399089009, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987444 + }, + { + "id": 399089010, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.11290800", + "quoteQty": "1318.26299940", + "time": 1598850987444 + }, + { + "id": 399089011, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987444 + }, + { + "id": 399089012, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987444 + }, + { + "id": 399089013, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00171200", + "quoteQty": "19.98854160", + "time": 1598850987444 + }, + { + "id": 399089014, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987444 + }, + { + "id": 399089015, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987449 + }, + { + "id": 399089016, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987449 + }, + { + "id": 399089017, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.20090200", + "quoteQty": "2345.64134610", + "time": 1598850987449 + }, + { + "id": 399089018, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01690200", + "quoteQty": "197.34014610", + "time": 1598850987449 + }, + { + "id": 399089019, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.02777000", + "quoteQty": "324.23002350", + "time": 1598850987451 + }, + { + "id": 399089020, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.03682800", + "quoteQty": "429.98715540", + "time": 1598850987451 + }, + { + "id": 399089021, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.24384400", + "quoteQty": "2847.01281420", + "time": 1598850987476 + }, + { + "id": 399089022, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00464200", + "quoteQty": "54.19790310", + "time": 1598850987476 + }, + { + "id": 399089023, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.33700900", + "quoteQty": "3934.76542995", + "time": 1598850987476 + }, + { + "id": 399089024, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.35281100", + "quoteQty": "4119.26247105", + "time": 1598850987529 + }, + { + "id": 399089025, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.21167100", + "quoteQty": "2471.37534405", + "time": 1598850987559 + }, + { + "id": 399089026, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.26129700", + "quoteQty": "3050.78618835", + "time": 1598850987606 + }, + { + "id": 399089027, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00171200", + "quoteQty": "19.98854160", + "time": 1598850987635 + }, + { + "id": 399089028, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00177300", + "quoteQty": "20.70075015", + "time": 1598850987638 + }, + { + "id": 399089029, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.01134400", + "quoteQty": "132.44743920", + "time": 1598850987730 + }, + { + "id": 399089030, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.55000000", + "qty": "0.00477200", + "quoteQty": "55.71572460", + "time": 1598850987930 + }, + { + "id": 399089031, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.44000000", + "qty": "0.01712900", + "quoteQty": "199.98861176", + "time": 1598850987989 + }, + { + "id": 399089032, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.43000000", + "qty": "0.00477200", + "quoteQty": "55.71515196", + "time": 1598850988033 + }, + { + "id": 399089033, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.43000000", + "qty": "0.00118400", + "quoteQty": "13.82370912", + "time": 1598850989008 + }, + { + "id": 399089034, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.43000000", + "qty": "0.00771900", + "quoteQty": "90.12264417", + "time": 1598850989304 + }, + { + "id": 399089035, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.92000000", + "qty": "0.00428100", + "quoteQty": "49.98033252", + "time": 1598850989304 + }, + { + "id": 399089036, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.19000000", + "qty": "0.01367500", + "quoteQty": "159.65822325", + "time": 1598850989386 + }, + { + "id": 399089037, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.39000000", + "qty": "0.00038900", + "quoteQty": "4.54172671", + "time": 1598850989386 + }, + { + "id": 399089038, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.00118900", + "quoteQty": "13.88191981", + "time": 1598850989795 + }, + { + "id": 399089039, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.01251000", + "quoteQty": "146.05787790", + "time": 1598850990179 + }, + { + "id": 399089040, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.03326600", + "quoteQty": "388.39019714", + "time": 1598850990179 + }, + { + "id": 399089041, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.03983900", + "quoteQty": "465.13187831", + "time": 1598850990287 + }, + { + "id": 399089042, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.40000000", + "qty": "0.01369900", + "quoteQty": "159.94130460", + "time": 1598850990618 + }, + { + "id": 399089043, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991508 + }, + { + "id": 399089044, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00642900", + "quoteQty": "75.06037512", + "time": 1598850991508 + }, + { + "id": 399089045, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00084100", + "quoteQty": "9.81891048", + "time": 1598850991508 + }, + { + "id": 399089046, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991508 + }, + { + "id": 399089047, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991508 + }, + { + "id": 399089048, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089049, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089050, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089051, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089052, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089053, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089054, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089055, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089056, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089057, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089058, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089059, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089060, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991509 + }, + { + "id": 399089061, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991510 + }, + { + "id": 399089062, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991510 + }, + { + "id": 399089063, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991510 + }, + { + "id": 399089064, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991510 + }, + { + "id": 399089065, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991510 + }, + { + "id": 399089066, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089067, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089068, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089069, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089070, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089071, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089072, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991511 + }, + { + "id": 399089073, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089074, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089075, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089076, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089077, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089078, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991512 + }, + { + "id": 399089079, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991513 + }, + { + "id": 399089080, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991513 + }, + { + "id": 399089081, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991513 + }, + { + "id": 399089082, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991513 + }, + { + "id": 399089083, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991513 + }, + { + "id": 399089084, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991514 + }, + { + "id": 399089085, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991514 + }, + { + "id": 399089086, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991519 + }, + { + "id": 399089087, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991519 + }, + { + "id": 399089088, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.00727000", + "quoteQty": "84.87928560", + "time": 1598850991520 + }, + { + "id": 399089089, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.08858300", + "quoteQty": "1034.23221407", + "time": 1598850991536 + }, + { + "id": 399089090, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.08145800", + "quoteQty": "951.04577282", + "time": 1598850991536 + }, + { + "id": 399089091, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.29000000", + "qty": "0.00900000", + "quoteQty": "105.07761000", + "time": 1598850991536 + }, + { + "id": 399089092, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.41000000", + "qty": "0.01369900", + "quoteQty": "159.94144159", + "time": 1598850991536 + }, + { + "id": 399089093, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.13440700", + "quoteQty": "1569.27699292", + "time": 1598850991536 + }, + { + "id": 399089094, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00171000", + "quoteQty": "19.96484850", + "time": 1598850992418 + }, + { + "id": 399089095, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00219000", + "quoteQty": "25.56901650", + "time": 1598850993194 + }, + { + "id": 399089096, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00425900", + "quoteQty": "49.72531565", + "time": 1598850994307 + }, + { + "id": 399089097, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.00553200", + "quoteQty": "64.58803620", + "time": 1598850994812 + }, + { + "id": 399089098, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.29000000", + "qty": "0.01371900", + "quoteQty": "160.17330351", + "time": 1598850994812 + }, + { + "id": 399089099, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.28000000", + "qty": "0.01369000", + "quoteQty": "159.83458320", + "time": 1598850994812 + }, + { + "id": 399089100, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.18000000", + "qty": "0.01367500", + "quoteQty": "159.65808650", + "time": 1598850994812 + }, + { + "id": 399089101, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.99000000", + "qty": "0.00885300", + "quoteQty": "103.35868647", + "time": 1598850994946 + }, + { + "id": 399089102, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.78000000", + "qty": "0.00713700", + "quoteQty": "83.32290486", + "time": 1598850994946 + }, + { + "id": 399089103, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.89000000", + "qty": "0.01369100", + "quoteQty": "159.84091899", + "time": 1598850995011 + }, + { + "id": 399089104, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.78000000", + "qty": "0.00223400", + "quoteQty": "26.08145852", + "time": 1598850995011 + }, + { + "id": 399089105, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.79000000", + "qty": "0.00101300", + "quoteQty": "11.82656227", + "time": 1598850995078 + }, + { + "id": 399089106, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.79000000", + "qty": "0.00167800", + "quoteQty": "19.59029762", + "time": 1598850995271 + }, + { + "id": 399089107, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.79000000", + "qty": "0.00979500", + "quoteQty": "114.35456805", + "time": 1598850995429 + }, + { + "id": 399089108, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11674.78000000", + "qty": "0.01068900", + "quoteQty": "124.79172342", + "time": 1598850995604 + }, + { + "id": 399089109, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.79000000", + "qty": "0.00121000", + "quoteQty": "14.12649590", + "time": 1598850995798 + }, + { + "id": 399089110, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.90000000", + "qty": "0.01369100", + "quoteQty": "159.84105590", + "time": 1598850995798 + }, + { + "id": 399089111, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11674.99000000", + "qty": "0.00651800", + "quoteQty": "76.09758482", + "time": 1598850995798 + }, + { + "id": 399089112, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.19000000", + "qty": "0.00707400", + "quoteQty": "82.59029406", + "time": 1598850995798 + }, + { + "id": 399089113, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.33000000", + "qty": "0.04196100", + "quoteQty": "489.90852213", + "time": 1598850995798 + }, + { + "id": 399089114, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.33000000", + "qty": "0.00000200", + "quoteQty": "0.02335066", + "time": 1598850995799 + }, + { + "id": 399089115, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.00722000", + "quoteQty": "84.29609920", + "time": 1598850995799 + }, + { + "id": 399089116, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.35000000", + "qty": "0.07751800", + "quoteQty": "905.04978130", + "time": 1598850995831 + }, + { + "id": 399089117, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.00647100", + "quoteQty": "75.55125456", + "time": 1598850995873 + }, + { + "id": 399089118, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.36000000", + "qty": "0.01369600", + "quoteQty": "159.90573056", + "time": 1598850995873 + }, + { + "id": 399089119, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00353200", + "quoteQty": "41.23751280", + "time": 1598850995873 + }, + { + "id": 399089120, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.43000000", + "qty": "0.00318600", + "quoteQty": "37.19791998", + "time": 1598850995873 + }, + { + "id": 399089121, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.43000000", + "qty": "0.01050400", + "quoteQty": "122.63871672", + "time": 1598850995881 + }, + { + "id": 399089122, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.56000000", + "qty": "0.06676300", + "quoteQty": "779.49541228", + "time": 1598850995881 + }, + { + "id": 399089123, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.45000000", + "qty": "0.00518500", + "quoteQty": "60.53720825", + "time": 1598850996753 + }, + { + "id": 399089124, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.45000000", + "qty": "0.00857300", + "quoteQty": "100.09363285", + "time": 1598850996946 + }, + { + "id": 399089125, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.45000000", + "qty": "0.03448700", + "quoteQty": "402.65124415", + "time": 1598850996946 + }, + { + "id": 399089126, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.46000000", + "qty": "0.01155400", + "quoteQty": "134.89826484", + "time": 1598850997340 + }, + { + "id": 399089127, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.23000000", + "qty": "0.27851100", + "quoteQty": "3251.67998253", + "time": 1598850997946 + }, + { + "id": 399089128, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.23000000", + "qty": "2.00000000", + "quoteQty": "23350.46000000", + "time": 1598850997946 + }, + { + "id": 399089129, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.23000000", + "qty": "0.04652500", + "quoteQty": "543.19007575", + "time": 1598850997946 + }, + { + "id": 399089130, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.34000000", + "qty": "0.01385000", + "quoteQty": "161.70345900", + "time": 1598850998006 + }, + { + "id": 399089131, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.35000000", + "qty": "0.01375800", + "quoteQty": "160.62946530", + "time": 1598850998006 + }, + { + "id": 399089132, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.15239200", + "quoteQty": "1779.23755680", + "time": 1598850998006 + }, + { + "id": 399089133, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00125200", + "quoteQty": "14.61758828", + "time": 1598850999924 + }, + { + "id": 399089134, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00211400", + "quoteQty": "24.68177446", + "time": 1598851000007 + }, + { + "id": 399089135, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00224000", + "quoteQty": "26.15289600", + "time": 1598851000818 + }, + { + "id": 399089136, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00734000", + "quoteQty": "85.69736260", + "time": 1598851001430 + }, + { + "id": 399089137, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00516700", + "quoteQty": "60.32674013", + "time": 1598851002109 + }, + { + "id": 399089138, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00779700", + "quoteQty": "91.03301583", + "time": 1598851002284 + }, + { + "id": 399089139, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.06421600", + "quoteQty": "749.74684424", + "time": 1598851002445 + }, + { + "id": 399089140, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.01354300", + "quoteQty": "158.11980677", + "time": 1598851002491 + }, + { + "id": 399089141, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.13120100", + "quoteQty": "1531.82284339", + "time": 1598851002554 + }, + { + "id": 399089142, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.46861200", + "quoteQty": "5471.22785868", + "time": 1598851002665 + }, + { + "id": 399089143, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00094200", + "quoteQty": "10.99822680", + "time": 1598851003307 + }, + { + "id": 399089144, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00827000", + "quoteQty": "96.55547530", + "time": 1598851003360 + }, + { + "id": 399089145, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00525600", + "quoteQty": "61.36590240", + "time": 1598851003731 + }, + { + "id": 399089146, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.05073100", + "quoteQty": "592.30421009", + "time": 1598851003832 + }, + { + "id": 399089147, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.03435900", + "quoteQty": "401.15472501", + "time": 1598851003832 + }, + { + "id": 399089148, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00092800", + "quoteQty": "10.83476192", + "time": 1598851004063 + }, + { + "id": 399089149, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00362300", + "quoteQty": "42.29997420", + "time": 1598851004444 + }, + { + "id": 399089150, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00856100", + "quoteQty": "99.95301379", + "time": 1598851004588 + }, + { + "id": 399089151, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00164400", + "quoteQty": "19.19435760", + "time": 1598851004662 + }, + { + "id": 399089152, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00692600", + "quoteQty": "80.86382040", + "time": 1598851004662 + }, + { + "id": 399089153, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00694200", + "quoteQty": "81.05055738", + "time": 1598851004665 + }, + { + "id": 399089154, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00961400", + "quoteQty": "112.24719946", + "time": 1598851004687 + }, + { + "id": 399089155, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.02006200", + "quoteQty": "234.23167418", + "time": 1598851005103 + }, + { + "id": 399089156, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.39000000", + "qty": "0.00150100", + "quoteQty": "17.52476039", + "time": 1598851005797 + }, + { + "id": 399089157, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.40000000", + "qty": "0.00128500", + "quoteQty": "15.00288900", + "time": 1598851005909 + }, + { + "id": 399089158, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.46000000", + "qty": "0.00220200", + "quoteQty": "25.70936292", + "time": 1598851006178 + }, + { + "id": 399089159, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.46000000", + "qty": "0.00000200", + "quoteQty": "0.02335092", + "time": 1598851006187 + }, + { + "id": 399089160, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.53000000", + "qty": "0.00433500", + "quoteQty": "50.61342255", + "time": 1598851006279 + }, + { + "id": 399089161, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.00096100", + "quoteQty": "11.22017472", + "time": 1598851006640 + }, + { + "id": 399089162, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.04903900", + "quoteQty": "572.55582528", + "time": 1598851006640 + }, + { + "id": 399089163, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.53000000", + "qty": "0.00244200", + "quoteQty": "28.51164426", + "time": 1598851007358 + }, + { + "id": 399089164, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.18549300", + "quoteQty": "2165.72723136", + "time": 1598851008610 + }, + { + "id": 399089165, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.03355200", + "quoteQty": "391.73704704", + "time": 1598851008708 + }, + { + "id": 399089166, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.53000000", + "qty": "0.00823200", + "quoteQty": "96.11296296", + "time": 1598851008785 + }, + { + "id": 399089167, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.57000000", + "qty": "0.01500000", + "quoteQty": "175.13355000", + "time": 1598851008785 + }, + { + "id": 399089168, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.70000000", + "qty": "0.01367500", + "quoteQty": "159.66519750", + "time": 1598851008785 + }, + { + "id": 399089169, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11675.82000000", + "qty": "0.00907300", + "quoteQty": "105.93471486", + "time": 1598851008785 + }, + { + "id": 399089170, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.00383200", + "quoteQty": "44.74243200", + "time": 1598851008785 + }, + { + "id": 399089171, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.06000000", + "qty": "0.02992200", + "quoteQty": "349.37106732", + "time": 1598851008785 + }, + { + "id": 399089172, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.14000000", + "qty": "0.01362500", + "quoteQty": "159.08740750", + "time": 1598851008785 + }, + { + "id": 399089173, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.29000000", + "qty": "0.10036800", + "quoteQty": "1171.92587472", + "time": 1598851008785 + }, + { + "id": 399089174, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.30000000", + "qty": "0.02627300", + "quoteQty": "306.77142990", + "time": 1598851008785 + }, + { + "id": 399089175, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00593700", + "quoteQty": "69.32035263", + "time": 1598851008915 + }, + { + "id": 399089176, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00243500", + "quoteQty": "28.43103565", + "time": 1598851009743 + }, + { + "id": 399089177, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00195600", + "quoteQty": "22.83823644", + "time": 1598851011352 + }, + { + "id": 399089178, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.00102700", + "quoteQty": "11.99125200", + "time": 1598851011701 + }, + { + "id": 399089179, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.01301000", + "quoteQty": "151.90462990", + "time": 1598851012115 + }, + { + "id": 399089180, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.00259500", + "quoteQty": "30.29919405", + "time": 1598851012467 + }, + { + "id": 399089181, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.01267800", + "quoteQty": "148.02832800", + "time": 1598851014935 + }, + { + "id": 399089182, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.00000000", + "qty": "0.00417000", + "quoteQty": "48.68892000", + "time": 1598851014935 + }, + { + "id": 399089183, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.27000000", + "qty": "0.00789300", + "quoteQty": "92.16079911", + "time": 1598851014935 + }, + { + "id": 399089184, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.27000000", + "qty": "0.00000200", + "quoteQty": "0.02335254", + "time": 1598851014939 + }, + { + "id": 399089185, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.33000000", + "qty": "0.00692200", + "quoteQty": "80.82355626", + "time": 1598851014939 + }, + { + "id": 399089186, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.00000000", + "qty": "0.03166600", + "quoteQty": "369.73221600", + "time": 1598851014958 + }, + { + "id": 399089187, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.32000000", + "qty": "0.07421800", + "quoteQty": "866.59311776", + "time": 1598851014976 + }, + { + "id": 399089188, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.03161400", + "quoteQty": "369.13581276", + "time": 1598851015013 + }, + { + "id": 399089189, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.33000000", + "qty": "0.01050800", + "quoteQty": "122.69487564", + "time": 1598851015118 + }, + { + "id": 399089190, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.33000000", + "qty": "0.34320000", + "quoteQty": "4007.31645600", + "time": 1598851015778 + }, + { + "id": 399089191, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.03563800", + "quoteQty": "416.12140492", + "time": 1598851015966 + }, + { + "id": 399089192, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.01365300", + "quoteQty": "159.41707002", + "time": 1598851015966 + }, + { + "id": 399089193, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.01858000", + "quoteQty": "216.94639720", + "time": 1598851015966 + }, + { + "id": 399089194, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.33000000", + "qty": "0.06755600", + "quoteQty": "788.80614948", + "time": 1598851015988 + }, + { + "id": 399089195, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.34000000", + "qty": "0.06775000", + "quoteQty": "791.07203500", + "time": 1598851016058 + }, + { + "id": 399089196, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.46000000", + "qty": "0.01358600", + "quoteQty": "158.63638556", + "time": 1598851016720 + }, + { + "id": 399089197, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.46000000", + "qty": "0.00003200", + "quoteQty": "0.37364672", + "time": 1598851018464 + }, + { + "id": 399089198, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.33000000", + "qty": "0.02459700", + "quoteQty": "287.20268901", + "time": 1598851018464 + }, + { + "id": 399089199, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.32000000", + "qty": "0.02806400", + "quoteQty": "327.68424448", + "time": 1598851018464 + }, + { + "id": 399089200, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.26000000", + "qty": "0.01804700", + "quoteQty": "210.72146422", + "time": 1598851018464 + }, + { + "id": 399089201, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.23000000", + "qty": "0.00603800", + "quoteQty": "70.50107674", + "time": 1598851018464 + }, + { + "id": 399089202, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11676.13000000", + "qty": "0.01365300", + "quoteQty": "159.41420289", + "time": 1598851018464 + }, + { + "id": 399089203, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.99000000", + "qty": "0.06777900", + "quoteQty": "791.38692621", + "time": 1598851018464 + }, + { + "id": 399089204, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.91000000", + "qty": "0.01370500", + "quoteQty": "160.01834655", + "time": 1598851018464 + }, + { + "id": 399089205, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.83000000", + "qty": "0.09374400", + "quoteQty": "1094.53900752", + "time": 1598851018464 + }, + { + "id": 399089206, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.56000000", + "qty": "1.12680300", + "quoteQty": "13156.05603468", + "time": 1598851018464 + }, + { + "id": 399089207, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.56000000", + "qty": "0.09374500", + "quoteQty": "1094.52537220", + "time": 1598851018465 + }, + { + "id": 399089208, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.00250300", + "quoteQty": "29.22382656", + "time": 1598851018471 + }, + { + "id": 399089209, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11675.52000000", + "qty": "0.33540900", + "quoteQty": "3916.07448768", + "time": 1598851018471 + }, + { + "id": 399089210, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.24000000", + "qty": "0.09766700", + "quoteQty": "1140.38333208", + "time": 1598851018491 + }, + { + "id": 399089211, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.02000000", + "qty": "0.01645100", + "quoteQty": "192.08220502", + "time": 1598851018515 + }, + { + "id": 399089212, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.02000000", + "qty": "0.00096900", + "quoteQty": "11.31406338", + "time": 1598851019935 + }, + { + "id": 399089213, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.02000000", + "qty": "0.01263300", + "quoteQty": "147.50316066", + "time": 1598851020255 + }, + { + "id": 399089214, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.02000000", + "qty": "0.11114600", + "quoteQty": "1297.74291892", + "time": 1598851020255 + }, + { + "id": 399089215, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.25000000", + "qty": "0.00936900", + "quoteQty": "109.39478625", + "time": 1598851020255 + }, + { + "id": 399089216, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.01361800", + "quoteQty": "159.01016846", + "time": 1598851020265 + }, + { + "id": 399089217, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.00096300", + "quoteQty": "11.24444061", + "time": 1598851020265 + }, + { + "id": 399089218, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.00541900", + "quoteQty": "63.27479093", + "time": 1598851020265 + }, + { + "id": 399089219, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.06213700", + "quoteQty": "725.54081639", + "time": 1598851020281 + }, + { + "id": 399089220, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.00181100", + "quoteQty": "21.14608717", + "time": 1598851020281 + }, + { + "id": 399089221, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.07421800", + "quoteQty": "866.60425046", + "time": 1598851020281 + }, + { + "id": 399089222, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.47000000", + "qty": "0.01360200", + "quoteQty": "158.82334494", + "time": 1598851020298 + }, + { + "id": 399089223, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.60000000", + "qty": "0.01367400", + "quoteQty": "159.66582840", + "time": 1598851020339 + }, + { + "id": 399089224, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.65000000", + "qty": "1.91074100", + "quoteQty": "22311.05389765", + "time": 1598851020339 + }, + { + "id": 399089225, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.80000000", + "qty": "0.01349800", + "quoteQty": "157.61344640", + "time": 1598851020339 + }, + { + "id": 399089226, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11676.95000000", + "qty": "0.05969200", + "quoteQty": "697.02049940", + "time": 1598851020339 + }, + { + "id": 399089227, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.01000000", + "qty": "0.01734800", + "quoteQty": "202.57276948", + "time": 1598851020344 + }, + { + "id": 399089228, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.57000000", + "qty": "0.01349800", + "quoteQty": "157.62383986", + "time": 1598851020344 + }, + { + "id": 399089229, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.58000000", + "qty": "0.00091000", + "quoteQty": "10.62659780", + "time": 1598851020344 + }, + { + "id": 399089230, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.73000000", + "qty": "0.01349800", + "quoteQty": "157.62599954", + "time": 1598851020344 + }, + { + "id": 399089231, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.93000000", + "qty": "0.00101400", + "quoteQty": "11.84142102", + "time": 1598851020344 + }, + { + "id": 399089232, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.15000000", + "qty": "0.01349800", + "quoteQty": "157.63166870", + "time": 1598851020344 + }, + { + "id": 399089233, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.24000000", + "qty": "0.00023400", + "quoteQty": "2.73270816", + "time": 1598851020344 + }, + { + "id": 399089234, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.03000000", + "qty": "0.00178500", + "quoteQty": "20.84528355", + "time": 1598851020452 + }, + { + "id": 399089235, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.78000000", + "qty": "0.00331100", + "quoteQty": "38.66512958", + "time": 1598851020504 + }, + { + "id": 399089236, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.78000000", + "qty": "0.00785000", + "quoteQty": "91.67057300", + "time": 1598851020716 + }, + { + "id": 399089237, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.78000000", + "qty": "0.00724400", + "quoteQty": "84.59383832", + "time": 1598851020956 + }, + { + "id": 399089238, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.79000000", + "qty": "0.01362300", + "quoteQty": "159.08653317", + "time": 1598851020969 + }, + { + "id": 399089239, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.78000000", + "qty": "0.00196500", + "quoteQty": "22.94683770", + "time": 1598851021095 + }, + { + "id": 399089240, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.78000000", + "qty": "0.00139300", + "quoteQty": "16.26714754", + "time": 1598851021249 + }, + { + "id": 399089241, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.79000000", + "qty": "0.00001200", + "quoteQty": "0.14013348", + "time": 1598851021677 + }, + { + "id": 399089242, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.80000000", + "qty": "0.01500000", + "quoteQty": "175.16700000", + "time": 1598851021677 + }, + { + "id": 399089243, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.03000000", + "qty": "0.00006800", + "quoteQty": "0.79410604", + "time": 1598851021677 + }, + { + "id": 399089244, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11677.91000000", + "qty": "0.01363500", + "quoteQty": "159.22830285", + "time": 1598851021791 + }, + { + "id": 399089245, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.03000000", + "qty": "0.00006100", + "quoteQty": "0.71235983", + "time": 1598851021791 + }, + { + "id": 399089246, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11677.90000000", + "qty": "0.00179500", + "quoteQty": "20.96183050", + "time": 1598851021798 + }, + { + "id": 399089247, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.00603300", + "quoteQty": "70.45349466", + "time": 1598851021899 + }, + { + "id": 399089248, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.01000000", + "qty": "0.00618400", + "quoteQty": "72.21681384", + "time": 1598851021905 + }, + { + "id": 399089249, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.00761300", + "quoteQty": "88.90476626", + "time": 1598851022042 + }, + { + "id": 399089250, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.01000000", + "qty": "0.03047300", + "quoteQty": "355.86399873", + "time": 1598851022290 + }, + { + "id": 399089251, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.00000500", + "quoteQty": "0.05839010", + "time": 1598851022315 + }, + { + "id": 399089252, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.03398000", + "quoteQty": "396.81911960", + "time": 1598851022315 + }, + { + "id": 399089253, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.01000000", + "qty": "0.00551300", + "quoteQty": "64.38086913", + "time": 1598851022840 + }, + { + "id": 399089254, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.00002000", + "quoteQty": "0.23356040", + "time": 1598851023373 + }, + { + "id": 399089255, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.02000000", + "qty": "0.01356700", + "quoteQty": "158.43569734", + "time": 1598851023373 + }, + { + "id": 399089256, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.03000000", + "qty": "0.01347800", + "quoteQty": "157.39648834", + "time": 1598851023915 + }, + { + "id": 399089257, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.02000000", + "qty": "0.19930000", + "quoteQty": "2327.42938600", + "time": 1598851024942 + }, + { + "id": 399089258, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.03000000", + "qty": "0.00002800", + "quoteQty": "0.32698484", + "time": 1598851024979 + }, + { + "id": 399089259, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.24000000", + "qty": "0.00178800", + "quoteQty": "20.88069312", + "time": 1598851024979 + }, + { + "id": 399089260, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.29000000", + "qty": "0.02000000", + "quoteQty": "233.56580000", + "time": 1598851024979 + }, + { + "id": 399089261, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.33000000", + "qty": "0.02483500", + "quoteQty": "290.03132555", + "time": 1598851024979 + }, + { + "id": 399089262, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.02000000", + "qty": "0.00211500", + "quoteQty": "24.69901230", + "time": 1598851024985 + }, + { + "id": 399089263, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.44000000", + "qty": "0.00142600", + "quoteQty": "16.65345544", + "time": 1598851025073 + }, + { + "id": 399089264, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.45000000", + "qty": "0.01348300", + "quoteQty": "157.46054135", + "time": 1598851025080 + }, + { + "id": 399089265, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.54000000", + "qty": "0.08206200", + "quoteQty": "958.36434948", + "time": 1598851025080 + }, + { + "id": 399089266, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.55000000", + "qty": "0.00979900", + "quoteQty": "114.43811145", + "time": 1598851025172 + }, + { + "id": 399089267, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.54000000", + "qty": "0.00259100", + "quoteQty": "30.25909714", + "time": 1598851025391 + }, + { + "id": 399089268, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.58000000", + "qty": "0.08563800", + "quoteQty": "1000.13023404", + "time": 1598851025493 + }, + { + "id": 399089269, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.54000000", + "qty": "0.00459000", + "quoteQty": "53.60449860", + "time": 1598851025499 + }, + { + "id": 399089270, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.58000000", + "qty": "0.00001500", + "quoteQty": "0.17517870", + "time": 1598851025830 + }, + { + "id": 399089271, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.99000000", + "qty": "0.00797600", + "quoteQty": "93.15162424", + "time": 1598851025830 + }, + { + "id": 399089272, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.78000000", + "qty": "0.01345100", + "quoteQty": "157.09126978", + "time": 1598851025921 + }, + { + "id": 399089273, + "isBestMatch": true, + "isBuyerMaker": true, + "price": "11678.78000000", + "qty": "0.03360400", + "quoteQty": "392.45372312", + "time": 1598851025921 + }, + { + "id": 399089274, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.79000000", + "qty": "0.01344100", + "quoteQty": "156.97461639", + "time": 1598851025929 + }, + { + "id": 399089275, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.79000000", + "qty": "0.00001000", + "quoteQty": "0.11678790", + "time": 1598851026011 + }, + { + "id": 399089276, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11678.99000000", + "qty": "0.04111800", + "quoteQty": "480.21671082", + "time": 1598851026011 + }, + { + "id": 399089277, + "isBestMatch": true, + "isBuyerMaker": false, + "price": "11679.00000000", + "qty": "0.00887200", + "quoteQty": "103.61608800", + "time": 1598851026011 + } + ], + "queryString": "limit=1000\u0026symbol=BTCUSDT", + "bodyParams": "", + "headers": {} } ] }, diff --git a/testdata/http_mock/bitstamp/bitstamp.json b/testdata/http_mock/bitstamp/bitstamp.json index 6f162e34..c104e14c 100644 --- a/testdata/http_mock/bitstamp/bitstamp.json +++ b/testdata/http_mock/bitstamp/bitstamp.json @@ -58568,6 +58568,451 @@ } ] }, + "/api/v2/transactions/ltcusd/": { + "GET": [ + { + "data": [ + { + "amount": "2.00000000", + "date": "1598850699", + "price": "62.28", + "tid": "121711825", + "type": "0" + }, + { + "amount": "1.08440000", + "date": "1598850609", + "price": "62.11", + "tid": "121711787", + "type": "0" + }, + { + "amount": "2.00000000", + "date": "1598850272", + "price": "62.11", + "tid": "121711653", + "type": "0" + }, + { + "amount": "14.90000000", + "date": "1598850242", + "price": "62.07", + "tid": "121711648", + "type": "1" + }, + { + "amount": "19.55000000", + "date": "1598850242", + "price": "62.07", + "tid": "121711647", + "type": "1" + }, + { + "amount": "1.04104000", + "date": "1598850155", + "price": "62.01", + "tid": "121711596", + "type": "0" + }, + { + "amount": "34.48212249", + "date": "1598850122", + "price": "61.98", + "tid": "121711563", + "type": "0" + }, + { + "amount": "2.00000000", + "date": "1598849987", + "price": "62.01", + "tid": "121711487", + "type": "0" + }, + { + "amount": "2.00000000", + "date": "1598849702", + "price": "62.13", + "tid": "121711399", + "type": "0" + }, + { + "amount": "36.07140000", + "date": "1598849685", + "price": "62.11", + "tid": "121711391", + "type": "0" + }, + { + "amount": "2.00000000", + "date": "1598849559", + "price": "62.05", + "tid": "121711359", + "type": "0" + }, + { + "amount": "32.17450000", + "date": "1598849474", + "price": "62.07", + "tid": "121711342", + "type": "0" + }, + { + "amount": "24.70980000", + "date": "1598849432", + "price": "62.05", + "tid": "121711336", + "type": "1" + }, + { + "amount": "1.99991000", + "date": "1598849417", + "price": "62.12", + "tid": "121711326", + "type": "0" + }, + { + "amount": "0.00009000", + "date": "1598849417", + "price": "62.10", + "tid": "121711325", + "type": "0" + }, + { + "amount": "1.05450000", + "date": "1598849374", + "price": "62.10", + "tid": "121711315", + "type": "0" + }, + { + "amount": "18.03147218", + "date": "1598849350", + "price": "62.02", + "tid": "121711304", + "type": "1" + }, + { + "amount": "2.00000000", + "date": "1598849132", + "price": "62.08", + "tid": "121711118", + "type": "0" + }, + { + "amount": "36.66000000", + "date": "1598848889", + "price": "62.23", + "tid": "121711054", + "type": "1" + }, + { + "amount": "1.20150000", + "date": "1598848862", + "price": "62.21", + "tid": "121711021", + "type": "0" + }, + { + "amount": "40.23600000", + "date": "1598848728", + "price": "62.18", + "tid": "121710973", + "type": "0" + }, + { + "amount": "40.24700000", + "date": "1598848728", + "price": "62.16", + "tid": "121710972", + "type": "0" + }, + { + "amount": "32.15560000", + "date": "1598848728", + "price": "62.16", + "tid": "121710971", + "type": "0" + }, + { + "amount": "35.81489175", + "date": "1598848632", + "price": "62.15", + "tid": "121710887", + "type": "1" + }, + { + "amount": "1.30000000", + "date": "1598848632", + "price": "62.15", + "tid": "121710886", + "type": "1" + }, + { + "amount": "36.86440000", + "date": "1598848500", + "price": "62.31", + "tid": "121710848", + "type": "0" + }, + { + "amount": "26.36586081", + "date": "1598848481", + "price": "62.28", + "tid": "121710843", + "type": "0" + }, + { + "amount": "32.08280000", + "date": "1598848480", + "price": "62.26", + "tid": "121710842", + "type": "0" + }, + { + "amount": "1.20369000", + "date": "1598848200", + "price": "62.14", + "tid": "121710730", + "type": "0" + }, + { + "amount": "34.36939918", + "date": "1598848199", + "price": "62.13", + "tid": "121710729", + "type": "0" + }, + { + "amount": "0.00651775", + "date": "1598848141", + "price": "62.10", + "tid": "121710707", + "type": "1" + }, + { + "amount": "21.65000000", + "date": "1598848141", + "price": "62.10", + "tid": "121710706", + "type": "1" + }, + { + "amount": "35.73000000", + "date": "1598848133", + "price": "62.11", + "tid": "121710700", + "type": "1" + }, + { + "amount": "24.70983044", + "date": "1598847991", + "price": "62.18", + "tid": "121710655", + "type": "0" + }, + { + "amount": "40.24200000", + "date": "1598847991", + "price": "62.17", + "tid": "121710654", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847991", + "price": "62.17", + "tid": "121710653", + "type": "0" + }, + { + "amount": "3.95183044", + "date": "1598847981", + "price": "62.18", + "tid": "121710635", + "type": "0" + }, + { + "amount": "1.00000000", + "date": "1598847981", + "price": "62.18", + "tid": "121710634", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847981", + "price": "62.18", + "tid": "121710633", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847981", + "price": "62.16", + "tid": "121710632", + "type": "0" + }, + { + "amount": "3.34348225", + "date": "1598847976", + "price": "62.10", + "tid": "121710631", + "type": "1" + }, + { + "amount": "0.00016161", + "date": "1598847976", + "price": "62.13", + "tid": "121710630", + "type": "1" + }, + { + "amount": "77.62030923", + "date": "1598847976", + "price": "62.13", + "tid": "121710629", + "type": "1" + }, + { + "amount": "0.00009077", + "date": "1598847976", + "price": "62.14", + "tid": "121710628", + "type": "1" + }, + { + "amount": "36.95090000", + "date": "1598847975", + "price": "62.14", + "tid": "121710627", + "type": "1" + }, + { + "amount": "23.69189460", + "date": "1598847971", + "price": "62.25", + "tid": "121710625", + "type": "0" + }, + { + "amount": "34.75993584", + "date": "1598847971", + "price": "62.24", + "tid": "121710624", + "type": "0" + }, + { + "amount": "6.50000000", + "date": "1598847971", + "price": "62.23", + "tid": "121710623", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847971", + "price": "62.20", + "tid": "121710622", + "type": "0" + }, + { + "amount": "29.66260607", + "date": "1598847960", + "price": "62.21", + "tid": "121710619", + "type": "0" + }, + { + "amount": "35.28922437", + "date": "1598847960", + "price": "62.20", + "tid": "121710618", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847960", + "price": "62.20", + "tid": "121710617", + "type": "0" + }, + { + "amount": "29.71394157", + "date": "1598847950", + "price": "62.24", + "tid": "121710612", + "type": "0" + }, + { + "amount": "35.23788887", + "date": "1598847950", + "price": "62.23", + "tid": "121710611", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847950", + "price": "62.22", + "tid": "121710610", + "type": "0" + }, + { + "amount": "32.07080000", + "date": "1598847940", + "price": "62.24", + "tid": "121710604", + "type": "1" + }, + { + "amount": "2.00000000", + "date": "1598847849", + "price": "62.29", + "tid": "121710575", + "type": "0" + }, + { + "amount": "36.83870000", + "date": "1598847667", + "price": "62.32", + "tid": "121710518", + "type": "1" + }, + { + "amount": "8.91000000", + "date": "1598847608", + "price": "62.44", + "tid": "121710464", + "type": "0" + }, + { + "amount": "0.00006000", + "date": "1598847607", + "price": "62.37", + "tid": "121710459", + "type": "0" + }, + { + "amount": "2.02070000", + "date": "1598847600", + "price": "62.37", + "tid": "121710432", + "type": "0" + }, + { + "amount": "60.00000000", + "date": "1598847484", + "price": "62.32", + "tid": "121710388", + "type": "1" + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, "/api/v2/transfer-to-main/": { "POST": [ { diff --git a/testdata/http_mock/gemini/gemini.json b/testdata/http_mock/gemini/gemini.json index 875777b9..d7854ec0 100644 --- a/testdata/http_mock/gemini/gemini.json +++ b/testdata/http_mock/gemini/gemini.json @@ -2156,6 +2156,18038 @@ } ] }, + "/v1/trades/BTCUSD": { + "GET": [ + { + "data": [ + { + "amount": "0.0002916", + "exchange": "gemini", + "price": "9593.65", + "tid": 607568549, + "timestamp": 1591404856, + "timestampms": 1591404856618, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.81", + "tid": 607568428, + "timestamp": 1591404846, + "timestampms": 1591404846471, + "type": "buy" + }, + { + "amount": "0.0002088", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568421, + "timestamp": 1591404836, + "timestampms": 1591404836328, + "type": "sell" + }, + { + "amount": "0.0006945", + "exchange": "gemini", + "price": "9593.81", + "tid": 607568416, + "timestamp": 1591404836, + "timestampms": 1591404836302, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568409, + "timestamp": 1591404826, + "timestampms": 1591404826149, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568403, + "timestamp": 1591404816, + "timestampms": 1591404816000, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568397, + "timestamp": 1591404805, + "timestampms": 1591404805856, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568325, + "timestamp": 1591404795, + "timestampms": 1591404795719, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568194, + "timestamp": 1591404785, + "timestampms": 1591404785573, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568188, + "timestamp": 1591404775, + "timestampms": 1591404775428, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568182, + "timestamp": 1591404765, + "timestampms": 1591404765296, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568176, + "timestamp": 1591404755, + "timestampms": 1591404755158, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568169, + "timestamp": 1591404745, + "timestampms": 1591404745019, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.46", + "tid": 607568123, + "timestamp": 1591404734, + "timestampms": 1591404734862, + "type": "buy" + }, + { + "amount": "0.061678", + "exchange": "gemini", + "price": "9588.46", + "tid": 607567994, + "timestamp": 1591404734, + "timestampms": 1591404734257, + "type": "buy" + }, + { + "amount": "1.7734732", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567924, + "timestamp": 1591404733, + "timestampms": 1591404733737, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567919, + "timestamp": 1591404733, + "timestampms": 1591404733713, + "type": "buy" + }, + { + "amount": "0.029082", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567914, + "timestamp": 1591404733, + "timestampms": 1591404733690, + "type": "buy" + }, + { + "amount": "0.035174", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567909, + "timestamp": 1591404733, + "timestampms": 1591404733667, + "type": "buy" + }, + { + "amount": "0.03108", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567904, + "timestamp": 1591404733, + "timestampms": 1591404733643, + "type": "buy" + }, + { + "amount": "0.0311908", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567899, + "timestamp": 1591404733, + "timestampms": 1591404733617, + "type": "buy" + }, + { + "amount": "0.1688092", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567897, + "timestamp": 1591404733, + "timestampms": 1591404733617, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567890, + "timestamp": 1591404724, + "timestampms": 1591404724719, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567883, + "timestamp": 1591404714, + "timestampms": 1591404714575, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567876, + "timestamp": 1591404704, + "timestampms": 1591404704420, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567870, + "timestamp": 1591404694, + "timestampms": 1591404694283, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567864, + "timestamp": 1591404684, + "timestampms": 1591404684139, + "type": "buy" + }, + { + "amount": "0.0006352", + "exchange": "gemini", + "price": "9583.20", + "tid": 607567840, + "timestamp": 1591404673, + "timestampms": 1591404673975, + "type": "sell" + }, + { + "amount": "0.0001298", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567832, + "timestamp": 1591404673, + "timestampms": 1591404673946, + "type": "buy" + }, + { + "amount": "1.345907", + "exchange": "gemini", + "price": "9588.08", + "tid": 607567686, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.02826", + "exchange": "gemini", + "price": "9588.09", + "tid": 607567684, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.9816", + "exchange": "gemini", + "price": "9588.72", + "tid": 607567682, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.023172", + "exchange": "gemini", + "price": "9588.73", + "tid": 607567680, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.021061", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567678, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.178939", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567673, + "timestamp": 1591404672, + "timestampms": 1591404672977, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567606, + "timestamp": 1591404663, + "timestampms": 1591404663783, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567600, + "timestamp": 1591404653, + "timestampms": 1591404653637, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567594, + "timestamp": 1591404643, + "timestampms": 1591404643497, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567586, + "timestamp": 1591404633, + "timestampms": 1591404633356, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567580, + "timestamp": 1591404623, + "timestampms": 1591404623188, + "type": "buy" + }, + { + "amount": "0.0003915", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567574, + "timestamp": 1591404613, + "timestampms": 1591404613023, + "type": "sell" + }, + { + "amount": "0.0004328", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567566, + "timestamp": 1591404612, + "timestampms": 1591404612995, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567382, + "timestamp": 1591404602, + "timestampms": 1591404602843, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567375, + "timestamp": 1591404592, + "timestampms": 1591404592697, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567368, + "timestamp": 1591404582, + "timestampms": 1591404582565, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567361, + "timestamp": 1591404572, + "timestampms": 1591404572384, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567355, + "timestamp": 1591404562, + "timestampms": 1591404562233, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567348, + "timestamp": 1591404552, + "timestampms": 1591404552063, + "type": "buy" + }, + { + "amount": "0.198334", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567149, + "timestamp": 1591404550, + "timestampms": 1591404550712, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567068, + "timestamp": 1591404541, + "timestampms": 1591404541922, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567061, + "timestamp": 1591404531, + "timestampms": 1591404531777, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567055, + "timestamp": 1591404521, + "timestampms": 1591404521641, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567048, + "timestamp": 1591404511, + "timestampms": 1591404511468, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567042, + "timestamp": 1591404501, + "timestampms": 1591404501328, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567035, + "timestamp": 1591404491, + "timestampms": 1591404491188, + "type": "buy" + }, + { + "amount": "0.1814453", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566854, + "timestamp": 1591404489, + "timestampms": 1591404489598, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566785, + "timestamp": 1591404481, + "timestampms": 1591404481038, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566778, + "timestamp": 1591404470, + "timestampms": 1591404470894, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566772, + "timestamp": 1591404460, + "timestampms": 1591404460754, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566766, + "timestamp": 1591404450, + "timestampms": 1591404450595, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566759, + "timestamp": 1591404440, + "timestampms": 1591404440451, + "type": "buy" + }, + { + "amount": "0.0005769", + "exchange": "gemini", + "price": "9571.23", + "tid": 607566752, + "timestamp": 1591404430, + "timestampms": 1591404430283, + "type": "sell" + }, + { + "amount": "0.0001397", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566747, + "timestamp": 1591404430, + "timestampms": 1591404430257, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566500, + "timestamp": 1591404420, + "timestampms": 1591404420101, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566494, + "timestamp": 1591404409, + "timestampms": 1591404409957, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566488, + "timestamp": 1591404399, + "timestampms": 1591404399816, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566481, + "timestamp": 1591404389, + "timestampms": 1591404389679, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566475, + "timestamp": 1591404379, + "timestampms": 1591404379537, + "type": "sell" + }, + { + "amount": "0.0002322", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566468, + "timestamp": 1591404369, + "timestampms": 1591404369398, + "type": "sell" + }, + { + "amount": "0.0001925", + "exchange": "gemini", + "price": "9578.76", + "tid": 607566463, + "timestamp": 1591404369, + "timestampms": 1591404369369, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566217, + "timestamp": 1591404359, + "timestampms": 1591404359231, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566210, + "timestamp": 1591404349, + "timestampms": 1591404349088, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566203, + "timestamp": 1591404338, + "timestampms": 1591404338881, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566197, + "timestamp": 1591404328, + "timestampms": 1591404328732, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566191, + "timestamp": 1591404318, + "timestampms": 1591404318587, + "type": "buy" + }, + { + "amount": "0.0009253", + "exchange": "gemini", + "price": "9574.55", + "tid": 607566184, + "timestamp": 1591404308, + "timestampms": 1591404308416, + "type": "sell" + }, + { + "amount": "0.0009995", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566179, + "timestamp": 1591404308, + "timestampms": 1591404308391, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565932, + "timestamp": 1591404298, + "timestampms": 1591404298242, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565926, + "timestamp": 1591404288, + "timestampms": 1591404288101, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565920, + "timestamp": 1591404277, + "timestampms": 1591404277964, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565913, + "timestamp": 1591404267, + "timestampms": 1591404267818, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9571.60", + "tid": 607565907, + "timestamp": 1591404257, + "timestampms": 1591404257649, + "type": "sell" + }, + { + "amount": "0.0005395", + "exchange": "gemini", + "price": "9571.60", + "tid": 607565900, + "timestamp": 1591404247, + "timestampms": 1591404247518, + "type": "sell" + }, + { + "amount": "0.0007753", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565895, + "timestamp": 1591404247, + "timestampms": 1591404247489, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565671, + "timestamp": 1591404237, + "timestampms": 1591404237349, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565664, + "timestamp": 1591404227, + "timestampms": 1591404227210, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565658, + "timestamp": 1591404217, + "timestampms": 1591404217073, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565652, + "timestamp": 1591404206, + "timestampms": 1591404206938, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565646, + "timestamp": 1591404196, + "timestampms": 1591404196773, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565639, + "timestamp": 1591404186, + "timestampms": 1591404186598, + "type": "buy" + }, + { + "amount": "0.1938328", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565455, + "timestamp": 1591404184, + "timestampms": 1591404184045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565377, + "timestamp": 1591404176, + "timestampms": 1591404176426, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565371, + "timestamp": 1591404166, + "timestampms": 1591404166248, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565365, + "timestamp": 1591404156, + "timestampms": 1591404156076, + "type": "sell" + }, + { + "amount": "0.000403", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565358, + "timestamp": 1591404145, + "timestampms": 1591404145937, + "type": "sell" + }, + { + "amount": "0.0000897", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565353, + "timestamp": 1591404145, + "timestampms": 1591404145912, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565346, + "timestamp": 1591404135, + "timestampms": 1591404135772, + "type": "buy" + }, + { + "amount": "0.0001711", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565339, + "timestamp": 1591404125, + "timestampms": 1591404125641, + "type": "sell" + }, + { + "amount": "0.0002345", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565334, + "timestamp": 1591404125, + "timestampms": 1591404125613, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565147, + "timestamp": 1591404115, + "timestampms": 1591404115468, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565140, + "timestamp": 1591404105, + "timestampms": 1591404105316, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565134, + "timestamp": 1591404095, + "timestampms": 1591404095175, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565128, + "timestamp": 1591404085, + "timestampms": 1591404085041, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565122, + "timestamp": 1591404074, + "timestampms": 1591404074879, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565115, + "timestamp": 1591404064, + "timestampms": 1591404064740, + "type": "buy" + }, + { + "amount": "0.09192", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564957, + "timestamp": 1591404061, + "timestampms": 1591404061872, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564890, + "timestamp": 1591404054, + "timestampms": 1591404054591, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564884, + "timestamp": 1591404044, + "timestampms": 1591404044425, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564877, + "timestamp": 1591404034, + "timestampms": 1591404034246, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564870, + "timestamp": 1591404024, + "timestampms": 1591404024079, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564864, + "timestamp": 1591404013, + "timestampms": 1591404013899, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564857, + "timestamp": 1591404003, + "timestampms": 1591404003723, + "type": "buy" + }, + { + "amount": "1.5550442", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564721, + "timestamp": 1591404000, + "timestampms": 1591404000815, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564713, + "timestamp": 1591404000, + "timestampms": 1591404000786, + "type": "buy" + }, + { + "amount": "0.9904", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564705, + "timestamp": 1591404000, + "timestampms": 1591404000760, + "type": "buy" + }, + { + "amount": "3.558782", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564656, + "timestamp": 1591404000, + "timestampms": 1591404000351, + "type": "buy" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564651, + "timestamp": 1591404000, + "timestampms": 1591404000328, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564646, + "timestamp": 1591404000, + "timestampms": 1591404000305, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564641, + "timestamp": 1591404000, + "timestampms": 1591404000282, + "type": "buy" + }, + { + "amount": "0.173295", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564636, + "timestamp": 1591404000, + "timestampms": 1591404000259, + "type": "buy" + }, + { + "amount": "0.085851", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564631, + "timestamp": 1591404000, + "timestampms": 1591404000235, + "type": "buy" + }, + { + "amount": "0.172072", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564626, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "2.7", + "exchange": "gemini", + "price": "9535.55", + "tid": 607564624, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "0.112207", + "exchange": "gemini", + "price": "9535.54", + "tid": 607564622, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "1.715721", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564620, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "0.9795", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564615, + "timestamp": 1591404000, + "timestampms": 1591404000186, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564610, + "timestamp": 1591404000, + "timestampms": 1591404000162, + "type": "buy" + }, + { + "amount": "0.804779", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564605, + "timestamp": 1591404000, + "timestampms": 1591404000136, + "type": "buy" + }, + { + "amount": "0.094457", + "exchange": "gemini", + "price": "9535.46", + "tid": 607564603, + "timestamp": 1591404000, + "timestampms": 1591404000135, + "type": "buy" + }, + { + "amount": "0.091164", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564601, + "timestamp": 1591404000, + "timestampms": 1591404000135, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564595, + "timestamp": 1591403993, + "timestampms": 1591403993583, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564588, + "timestamp": 1591403983, + "timestampms": 1591403983430, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564582, + "timestamp": 1591403973, + "timestampms": 1591403973279, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564576, + "timestamp": 1591403963, + "timestampms": 1591403963041, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564570, + "timestamp": 1591403952, + "timestampms": 1591403952900, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564563, + "timestamp": 1591403942, + "timestampms": 1591403942758, + "type": "buy" + }, + { + "amount": "0.2545558", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564440, + "timestamp": 1591403939, + "timestampms": 1591403939725, + "type": "sell" + }, + { + "amount": "4.7", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564432, + "timestamp": 1591403939, + "timestampms": 1591403939699, + "type": "sell" + }, + { + "amount": "0.0271442", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564424, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9540.52", + "tid": 607564422, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9541.14", + "tid": 607564420, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "2.1628558", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564418, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.112207", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564407, + "timestamp": 1591403939, + "timestampms": 1591403939647, + "type": "sell" + }, + { + "amount": "2.4249372", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564402, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9543.74", + "tid": 607564400, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.9971", + "exchange": "gemini", + "price": "9544.24", + "tid": 607564398, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.0779628", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564396, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.094457", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564391, + "timestamp": 1591403939, + "timestampms": 1591403939598, + "type": "sell" + }, + { + "amount": "0.0275802", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564386, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.041524", + "exchange": "gemini", + "price": "9546.27", + "tid": 607564384, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.0340598", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564382, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564320, + "timestamp": 1591403932, + "timestampms": 1591403932613, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564312, + "timestamp": 1591403922, + "timestampms": 1591403922469, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564305, + "timestamp": 1591403912, + "timestampms": 1591403912313, + "type": "sell" + }, + { + "amount": "0.0014642", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564299, + "timestamp": 1591403902, + "timestampms": 1591403902171, + "type": "sell" + }, + { + "amount": "0.0005358", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564297, + "timestamp": 1591403902, + "timestampms": 1591403902171, + "type": "sell" + }, + { + "amount": "0.0004642", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564290, + "timestamp": 1591403892, + "timestampms": 1591403892021, + "type": "sell" + }, + { + "amount": "0.000236", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564288, + "timestamp": 1591403892, + "timestampms": 1591403892021, + "type": "sell" + }, + { + "amount": "0.0000285", + "exchange": "gemini", + "price": "9551.03", + "tid": 607564283, + "timestamp": 1591403891, + "timestampms": 1591403891994, + "type": "buy" + }, + { + "amount": "0.000764", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564277, + "timestamp": 1591403881, + "timestampms": 1591403881842, + "type": "sell" + }, + { + "amount": "0.0005176", + "exchange": "gemini", + "price": "9551.03", + "tid": 607564272, + "timestamp": 1591403881, + "timestampms": 1591403881807, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564048, + "timestamp": 1591403871, + "timestampms": 1591403871634, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564042, + "timestamp": 1591403861, + "timestampms": 1591403861464, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564036, + "timestamp": 1591403851, + "timestampms": 1591403851320, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564030, + "timestamp": 1591403841, + "timestampms": 1591403841152, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9548.22", + "tid": 607564023, + "timestamp": 1591403831, + "timestampms": 1591403831004, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9548.22", + "tid": 607564017, + "timestamp": 1591403820, + "timestampms": 1591403820847, + "type": "sell" + }, + { + "amount": "0.09552", + "exchange": "gemini", + "price": "9550.68", + "tid": 607563954, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.093063", + "exchange": "gemini", + "price": "9550.69", + "tid": 607563952, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.093063", + "exchange": "gemini", + "price": "9550.70", + "tid": 607563950, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "9550.71", + "tid": 607563948, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.273359", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563850, + "timestamp": 1591403817, + "timestampms": 1591403817384, + "type": "sell" + }, + { + "amount": "0.208861", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563845, + "timestamp": 1591403817, + "timestampms": 1591403817360, + "type": "sell" + }, + { + "amount": "0.01778", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563840, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9558.14", + "tid": 607563838, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.17222", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563836, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.018562", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563831, + "timestamp": 1591403817, + "timestampms": 1591403817312, + "type": "sell" + }, + { + "amount": "0.009218", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563826, + "timestamp": 1591403817, + "timestampms": 1591403817287, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563763, + "timestamp": 1591403810, + "timestampms": 1591403810702, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563757, + "timestamp": 1591403800, + "timestampms": 1591403800558, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563749, + "timestamp": 1591403790, + "timestampms": 1591403790419, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563743, + "timestamp": 1591403780, + "timestampms": 1591403780275, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563736, + "timestamp": 1591403770, + "timestampms": 1591403770131, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607563730, + "timestamp": 1591403759, + "timestampms": 1591403759974, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563491, + "timestamp": 1591403749, + "timestampms": 1591403749830, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563485, + "timestamp": 1591403739, + "timestampms": 1591403739675, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563477, + "timestamp": 1591403729, + "timestampms": 1591403729529, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563471, + "timestamp": 1591403719, + "timestampms": 1591403719380, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563464, + "timestamp": 1591403709, + "timestampms": 1591403709204, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563458, + "timestamp": 1591403699, + "timestampms": 1591403699047, + "type": "buy" + }, + { + "amount": "0.016213", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563216, + "timestamp": 1591403694, + "timestampms": 1591403694631, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563210, + "timestamp": 1591403688, + "timestampms": 1591403688883, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563204, + "timestamp": 1591403678, + "timestampms": 1591403678743, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563196, + "timestamp": 1591403668, + "timestampms": 1591403668586, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563190, + "timestamp": 1591403658, + "timestampms": 1591403658442, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563183, + "timestamp": 1591403648, + "timestampms": 1591403648304, + "type": "buy" + }, + { + "amount": "0.0006749", + "exchange": "gemini", + "price": "9569.71", + "tid": 607563177, + "timestamp": 1591403638, + "timestampms": 1591403638149, + "type": "sell" + }, + { + "amount": "0.0005197", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563172, + "timestamp": 1591403638, + "timestampms": 1591403638117, + "type": "buy" + }, + { + "amount": "0.047256", + "exchange": "gemini", + "price": "9572.81", + "tid": 607562996, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.040922", + "exchange": "gemini", + "price": "9572.83", + "tid": 607562994, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.030111", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562992, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562927, + "timestamp": 1591403627, + "timestampms": 1591403627973, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562921, + "timestamp": 1591403617, + "timestampms": 1591403617803, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562914, + "timestamp": 1591403607, + "timestampms": 1591403607657, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562908, + "timestamp": 1591403597, + "timestampms": 1591403597509, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562901, + "timestamp": 1591403587, + "timestampms": 1591403587367, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562894, + "timestamp": 1591403577, + "timestampms": 1591403577178, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562832, + "timestamp": 1591403573, + "timestampms": 1591403573314, + "type": "sell" + }, + { + "amount": "0.0002187", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562646, + "timestamp": 1591403567, + "timestampms": 1591403567031, + "type": "sell" + }, + { + "amount": "0.0004303", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562641, + "timestamp": 1591403567, + "timestampms": 1591403567002, + "type": "buy" + }, + { + "amount": "0.0004764", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562635, + "timestamp": 1591403556, + "timestampms": 1591403556865, + "type": "sell" + }, + { + "amount": "0.0000585", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562630, + "timestamp": 1591403556, + "timestampms": 1591403556837, + "type": "buy" + }, + { + "amount": "0.0003351", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562622, + "timestamp": 1591403546, + "timestampms": 1591403546679, + "type": "sell" + }, + { + "amount": "0.0008963", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562617, + "timestamp": 1591403546, + "timestampms": 1591403546652, + "type": "buy" + }, + { + "amount": "0.00029", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562611, + "timestamp": 1591403536, + "timestampms": 1591403536489, + "type": "sell" + }, + { + "amount": "0.0009719", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562606, + "timestamp": 1591403536, + "timestampms": 1591403536463, + "type": "buy" + }, + { + "amount": "0.0007671", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562599, + "timestamp": 1591403526, + "timestampms": 1591403526320, + "type": "sell" + }, + { + "amount": "0.0004812", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562594, + "timestamp": 1591403526, + "timestampms": 1591403526293, + "type": "buy" + }, + { + "amount": "0.000408", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562587, + "timestamp": 1591403516, + "timestampms": 1591403516146, + "type": "sell" + }, + { + "amount": "0.0009649", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562582, + "timestamp": 1591403516, + "timestampms": 1591403516117, + "type": "buy" + }, + { + "amount": "0.0009456", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562335, + "timestamp": 1591403505, + "timestampms": 1591403505931, + "type": "sell" + }, + { + "amount": "0.0005362", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562330, + "timestamp": 1591403505, + "timestampms": 1591403505904, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562324, + "timestamp": 1591403495, + "timestampms": 1591403495761, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562317, + "timestamp": 1591403485, + "timestampms": 1591403485618, + "type": "buy" + }, + { + "amount": "0.0002386", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562311, + "timestamp": 1591403475, + "timestampms": 1591403475455, + "type": "sell" + }, + { + "amount": "0.0001172", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562306, + "timestamp": 1591403475, + "timestampms": 1591403475429, + "type": "buy" + }, + { + "amount": "0.000214", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562298, + "timestamp": 1591403465, + "timestampms": 1591403465287, + "type": "sell" + }, + { + "amount": "0.0006639", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562293, + "timestamp": 1591403465, + "timestampms": 1591403465261, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562287, + "timestamp": 1591403455, + "timestampms": 1591403455126, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562041, + "timestamp": 1591403444, + "timestampms": 1591403444989, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562034, + "timestamp": 1591403434, + "timestampms": 1591403434852, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562027, + "timestamp": 1591403424, + "timestampms": 1591403424702, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562020, + "timestamp": 1591403414, + "timestampms": 1591403414550, + "type": "sell" + }, + { + "amount": "0.0007981", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562013, + "timestamp": 1591403404, + "timestampms": 1591403404404, + "type": "sell" + }, + { + "amount": "0.0008822", + "exchange": "gemini", + "price": "9588.51", + "tid": 607562008, + "timestamp": 1591403404, + "timestampms": 1591403404379, + "type": "buy" + }, + { + "amount": "0.000424", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562001, + "timestamp": 1591403394, + "timestampms": 1591403394242, + "type": "sell" + }, + { + "amount": "0.0007653", + "exchange": "gemini", + "price": "9588.51", + "tid": 607561996, + "timestamp": 1591403394, + "timestampms": 1591403394217, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561749, + "timestamp": 1591403384, + "timestampms": 1591403384076, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561743, + "timestamp": 1591403373, + "timestampms": 1591403373932, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561736, + "timestamp": 1591403363, + "timestampms": 1591403363787, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561730, + "timestamp": 1591403353, + "timestampms": 1591403353618, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.91", + "tid": 607561723, + "timestamp": 1591403343, + "timestampms": 1591403343474, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.91", + "tid": 607561717, + "timestamp": 1591403333, + "timestampms": 1591403333305, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561477, + "timestamp": 1591403323, + "timestampms": 1591403323168, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561469, + "timestamp": 1591403312, + "timestampms": 1591403312989, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561462, + "timestamp": 1591403302, + "timestampms": 1591403302826, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561456, + "timestamp": 1591403292, + "timestampms": 1591403292681, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561448, + "timestamp": 1591403282, + "timestampms": 1591403282520, + "type": "sell" + }, + { + "amount": "0.001592", + "exchange": "gemini", + "price": "9592.05", + "tid": 607561440, + "timestamp": 1591403272, + "timestampms": 1591403272375, + "type": "buy" + }, + { + "amount": "0.000204", + "exchange": "gemini", + "price": "9588.48", + "tid": 607561438, + "timestamp": 1591403272, + "timestampms": 1591403272374, + "type": "buy" + }, + { + "amount": "0.000204", + "exchange": "gemini", + "price": "9588.48", + "tid": 607561436, + "timestamp": 1591403272, + "timestampms": 1591403272374, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561190, + "timestamp": 1591403262, + "timestampms": 1591403262231, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561183, + "timestamp": 1591403252, + "timestampms": 1591403252090, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561177, + "timestamp": 1591403241, + "timestampms": 1591403241947, + "type": "buy" + }, + { + "amount": "0.0000292", + "exchange": "gemini", + "price": "9586.80", + "tid": 607561170, + "timestamp": 1591403231, + "timestampms": 1591403231777, + "type": "sell" + }, + { + "amount": "0.0009821", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561165, + "timestamp": 1591403231, + "timestampms": 1591403231741, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561158, + "timestamp": 1591403221, + "timestampms": 1591403221561, + "type": "buy" + }, + { + "amount": "0.0000987", + "exchange": "gemini", + "price": "9586.80", + "tid": 607561151, + "timestamp": 1591403211, + "timestampms": 1591403211383, + "type": "sell" + }, + { + "amount": "0.0009426", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561146, + "timestamp": 1591403211, + "timestampms": 1591403211358, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560900, + "timestamp": 1591403201, + "timestampms": 1591403201204, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560892, + "timestamp": 1591403191, + "timestampms": 1591403191066, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.78", + "tid": 607560886, + "timestamp": 1591403180, + "timestampms": 1591403180919, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.78", + "tid": 607560879, + "timestamp": 1591403170, + "timestampms": 1591403170773, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560872, + "timestamp": 1591403160, + "timestampms": 1591403160632, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560865, + "timestamp": 1591403150, + "timestampms": 1591403150478, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560643, + "timestamp": 1591403140, + "timestampms": 1591403140334, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560636, + "timestamp": 1591403130, + "timestampms": 1591403130189, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.84", + "tid": 607560629, + "timestamp": 1591403120, + "timestampms": 1591403120037, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.84", + "tid": 607560622, + "timestamp": 1591403109, + "timestampms": 1591403109901, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560615, + "timestamp": 1591403099, + "timestampms": 1591403099753, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560609, + "timestamp": 1591403089, + "timestampms": 1591403089621, + "type": "buy" + }, + { + "amount": "0.049741", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560427, + "timestamp": 1591403083, + "timestampms": 1591403083750, + "type": "buy" + }, + { + "amount": "0.140535", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560419, + "timestamp": 1591403083, + "timestampms": 1591403083724, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560354, + "timestamp": 1591403079, + "timestampms": 1591403079469, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560346, + "timestamp": 1591403069, + "timestampms": 1591403069242, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560339, + "timestamp": 1591403059, + "timestampms": 1591403059096, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560333, + "timestamp": 1591403048, + "timestampms": 1591403048954, + "type": "buy" + }, + { + "amount": "0.001724", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560327, + "timestamp": 1591403038, + "timestampms": 1591403038792, + "type": "buy" + }, + { + "amount": "0.000276", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560325, + "timestamp": 1591403038, + "timestampms": 1591403038792, + "type": "buy" + }, + { + "amount": "0.000862", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560318, + "timestamp": 1591403028, + "timestampms": 1591403028651, + "type": "buy" + }, + { + "amount": "0.001138", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560316, + "timestamp": 1591403028, + "timestampms": 1591403028651, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560075, + "timestamp": 1591403018, + "timestampms": 1591403018513, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560068, + "timestamp": 1591403008, + "timestampms": 1591403008372, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560062, + "timestamp": 1591402998, + "timestampms": 1591402998210, + "type": "sell" + }, + { + "amount": "0.0005549", + "exchange": "gemini", + "price": "9581.41", + "tid": 607560055, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.001138", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560053, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.0003071", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560051, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560044, + "timestamp": 1591402977, + "timestampms": 1591402977892, + "type": "sell" + }, + { + "amount": "0.0006934", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560038, + "timestamp": 1591402967, + "timestampms": 1591402967753, + "type": "sell" + }, + { + "amount": "0.0008309", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560033, + "timestamp": 1591402967, + "timestampms": 1591402967728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559787, + "timestamp": 1591402957, + "timestampms": 1591402957585, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559779, + "timestamp": 1591402947, + "timestampms": 1591402947433, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559773, + "timestamp": 1591402937, + "timestampms": 1591402937292, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559766, + "timestamp": 1591402927, + "timestampms": 1591402927155, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559758, + "timestamp": 1591402917, + "timestampms": 1591402917014, + "type": "sell" + }, + { + "amount": "0.0003975", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559751, + "timestamp": 1591402906, + "timestampms": 1591402906876, + "type": "sell" + }, + { + "amount": "0.0004107", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559746, + "timestamp": 1591402906, + "timestampms": 1591402906849, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559506, + "timestamp": 1591402896, + "timestampms": 1591402896705, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559499, + "timestamp": 1591402886, + "timestampms": 1591402886564, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559493, + "timestamp": 1591402876, + "timestampms": 1591402876423, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559486, + "timestamp": 1591402866, + "timestampms": 1591402866273, + "type": "sell" + }, + { + "amount": "0.0003464", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559479, + "timestamp": 1591402856, + "timestampms": 1591402856131, + "type": "sell" + }, + { + "amount": "0.0005546", + "exchange": "gemini", + "price": "9583.04", + "tid": 607559474, + "timestamp": 1591402856, + "timestampms": 1591402856102, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.04", + "tid": 607559468, + "timestamp": 1591402845, + "timestampms": 1591402845958, + "type": "buy" + }, + { + "amount": "0.041068", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559303, + "timestamp": 1591402839, + "timestampms": 1591402839358, + "type": "sell" + }, + { + "amount": "0.049136", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559295, + "timestamp": 1591402839, + "timestampms": 1591402839333, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559218, + "timestamp": 1591402835, + "timestampms": 1591402835798, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559210, + "timestamp": 1591402825, + "timestampms": 1591402825656, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559203, + "timestamp": 1591402815, + "timestampms": 1591402815498, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559196, + "timestamp": 1591402805, + "timestampms": 1591402805357, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559189, + "timestamp": 1591402795, + "timestampms": 1591402795216, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559182, + "timestamp": 1591402785, + "timestampms": 1591402785043, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607559002, + "timestamp": 1591402774, + "timestampms": 1591402774902, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558995, + "timestamp": 1591402764, + "timestampms": 1591402764757, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558989, + "timestamp": 1591402754, + "timestampms": 1591402754626, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558982, + "timestamp": 1591402744, + "timestampms": 1591402744487, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558976, + "timestamp": 1591402734, + "timestampms": 1591402734348, + "type": "buy" + }, + { + "amount": "0.001644", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558970, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.000178", + "exchange": "gemini", + "price": "9587.81", + "tid": 607558968, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.000178", + "exchange": "gemini", + "price": "9587.81", + "tid": 607558966, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.389845", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558803, + "timestamp": 1591402717, + "timestampms": 1591402717175, + "type": "buy" + }, + { + "amount": "0.598155", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558795, + "timestamp": 1591402717, + "timestampms": 1591402717151, + "type": "buy" + }, + { + "amount": "4", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558787, + "timestamp": 1591402717, + "timestampms": 1591402717127, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558692, + "timestamp": 1591402714, + "timestampms": 1591402714077, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558684, + "timestamp": 1591402703, + "timestampms": 1591402703937, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558678, + "timestamp": 1591402693, + "timestampms": 1591402693794, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558671, + "timestamp": 1591402683, + "timestampms": 1591402683639, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558664, + "timestamp": 1591402673, + "timestampms": 1591402673488, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558657, + "timestamp": 1591402663, + "timestampms": 1591402663343, + "type": "buy" + }, + { + "amount": "0.188744", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558488, + "timestamp": 1591402656, + "timestampms": 1591402656027, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558404, + "timestamp": 1591402653, + "timestampms": 1591402653199, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558397, + "timestamp": 1591402643, + "timestampms": 1591402643061, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558391, + "timestamp": 1591402632, + "timestampms": 1591402632925, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558384, + "timestamp": 1591402622, + "timestampms": 1591402622788, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558378, + "timestamp": 1591402612, + "timestampms": 1591402612642, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558370, + "timestamp": 1591402602, + "timestampms": 1591402602467, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558122, + "timestamp": 1591402592, + "timestampms": 1591402592328, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558116, + "timestamp": 1591402582, + "timestampms": 1591402582181, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558109, + "timestamp": 1591402572, + "timestampms": 1591402572040, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558103, + "timestamp": 1591402561, + "timestampms": 1591402561895, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558095, + "timestamp": 1591402551, + "timestampms": 1591402551737, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558089, + "timestamp": 1591402541, + "timestampms": 1591402541578, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557848, + "timestamp": 1591402531, + "timestampms": 1591402531426, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557842, + "timestamp": 1591402521, + "timestampms": 1591402521272, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557835, + "timestamp": 1591402511, + "timestampms": 1591402511136, + "type": "sell" + }, + { + "amount": "0.00184", + "exchange": "gemini", + "price": "9578.40", + "tid": 607557829, + "timestamp": 1591402500, + "timestampms": 1591402500995, + "type": "buy" + }, + { + "amount": "0.00016", + "exchange": "gemini", + "price": "9573.15", + "tid": 607557827, + "timestamp": 1591402500, + "timestampms": 1591402500995, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557820, + "timestamp": 1591402490, + "timestampms": 1591402490847, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557814, + "timestamp": 1591402480, + "timestampms": 1591402480707, + "type": "sell" + }, + { + "amount": "0.00016", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557635, + "timestamp": 1591402472, + "timestampms": 1591402472482, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557570, + "timestamp": 1591402470, + "timestampms": 1591402470559, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557564, + "timestamp": 1591402460, + "timestampms": 1591402460385, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557557, + "timestamp": 1591402450, + "timestampms": 1591402450249, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557551, + "timestamp": 1591402440, + "timestampms": 1591402440111, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557544, + "timestamp": 1591402429, + "timestampms": 1591402429971, + "type": "buy" + }, + { + "amount": "0.001692", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557538, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.000154", + "exchange": "gemini", + "price": "9573.76", + "tid": 607557536, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.000154", + "exchange": "gemini", + "price": "9573.76", + "tid": 607557534, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607557295, + "timestamp": 1591402409, + "timestampms": 1591402409663, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607557289, + "timestamp": 1591402399, + "timestampms": 1591402399492, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557282, + "timestamp": 1591402389, + "timestampms": 1591402389341, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557276, + "timestamp": 1591402379, + "timestampms": 1591402379192, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557269, + "timestamp": 1591402369, + "timestampms": 1591402369056, + "type": "buy" + }, + { + "amount": "0.001432", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557263, + "timestamp": 1591402358, + "timestampms": 1591402358915, + "type": "buy" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9570.79", + "tid": 607557261, + "timestamp": 1591402358, + "timestampms": 1591402358915, + "type": "buy" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9574.60", + "tid": 607557082, + "timestamp": 1591402350, + "timestampms": 1591402350133, + "type": "sell" + }, + { + "amount": "0.199432", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557080, + "timestamp": 1591402350, + "timestampms": 1591402350133, + "type": "sell" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557075, + "timestamp": 1591402350, + "timestampms": 1591402350103, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557010, + "timestamp": 1591402348, + "timestampms": 1591402348773, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557004, + "timestamp": 1591402338, + "timestampms": 1591402338629, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556997, + "timestamp": 1591402328, + "timestampms": 1591402328482, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556991, + "timestamp": 1591402318, + "timestampms": 1591402318335, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556983, + "timestamp": 1591402308, + "timestampms": 1591402308184, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556977, + "timestamp": 1591402298, + "timestampms": 1591402298050, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.61", + "tid": 607556730, + "timestamp": 1591402287, + "timestampms": 1591402287901, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.61", + "tid": 607556724, + "timestamp": 1591402277, + "timestampms": 1591402277767, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556717, + "timestamp": 1591402267, + "timestampms": 1591402267632, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556710, + "timestamp": 1591402257, + "timestampms": 1591402257488, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556704, + "timestamp": 1591402247, + "timestampms": 1591402247330, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556698, + "timestamp": 1591402237, + "timestampms": 1591402237187, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556450, + "timestamp": 1591402227, + "timestampms": 1591402227039, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556444, + "timestamp": 1591402216, + "timestampms": 1591402216896, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556437, + "timestamp": 1591402206, + "timestampms": 1591402206753, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556430, + "timestamp": 1591402196, + "timestampms": 1591402196549, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556423, + "timestamp": 1591402186, + "timestampms": 1591402186376, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556417, + "timestamp": 1591402176, + "timestampms": 1591402176219, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556176, + "timestamp": 1591402166, + "timestampms": 1591402166053, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556170, + "timestamp": 1591402155, + "timestampms": 1591402155900, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556162, + "timestamp": 1591402145, + "timestampms": 1591402145728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556156, + "timestamp": 1591402135, + "timestampms": 1591402135581, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556150, + "timestamp": 1591402125, + "timestampms": 1591402125396, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556143, + "timestamp": 1591402115, + "timestampms": 1591402115219, + "type": "buy" + }, + { + "amount": "0.364422", + "exchange": "gemini", + "price": "9582.65", + "tid": 607555989, + "timestamp": 1591402105, + "timestampms": 1591402105761, + "type": "sell" + }, + { + "amount": "0.100578", + "exchange": "gemini", + "price": "9582.65", + "tid": 607555984, + "timestamp": 1591402105, + "timestampms": 1591402105737, + "type": "sell" + }, + { + "amount": "0.193611", + "exchange": "gemini", + "price": "9584.35", + "tid": 607555982, + "timestamp": 1591402105, + "timestampms": 1591402105737, + "type": "sell" + }, + { + "amount": "0.306389", + "exchange": "gemini", + "price": "9584.35", + "tid": 607555977, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "1.9955", + "exchange": "gemini", + "price": "9585.04", + "tid": 607555975, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.128996", + "exchange": "gemini", + "price": "9586.83", + "tid": 607555973, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.114062", + "exchange": "gemini", + "price": "9586.84", + "tid": 607555971, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.108465", + "exchange": "gemini", + "price": "9587.00", + "tid": 607555969, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9587.29", + "tid": 607555967, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.9", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555965, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555900, + "timestamp": 1591402105, + "timestampms": 1591402105034, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555893, + "timestamp": 1591402094, + "timestampms": 1591402094884, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555886, + "timestamp": 1591402084, + "timestampms": 1591402084745, + "type": "sell" + }, + { + "amount": "0.0005071", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555879, + "timestamp": 1591402074, + "timestampms": 1591402074593, + "type": "sell" + }, + { + "amount": "0.0006448", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555874, + "timestamp": 1591402074, + "timestampms": 1591402074564, + "type": "buy" + }, + { + "amount": "0.0004319", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555867, + "timestamp": 1591402064, + "timestampms": 1591402064383, + "type": "sell" + }, + { + "amount": "0.0008555", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555862, + "timestamp": 1591402064, + "timestampms": 1591402064357, + "type": "buy" + }, + { + "amount": "0.0004368", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555856, + "timestamp": 1591402054, + "timestampms": 1591402054212, + "type": "sell" + }, + { + "amount": "0.0006728", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555851, + "timestamp": 1591402054, + "timestampms": 1591402054186, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555652, + "timestamp": 1591402044, + "timestampms": 1591402044042, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555646, + "timestamp": 1591402033, + "timestampms": 1591402033899, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555639, + "timestamp": 1591402023, + "timestampms": 1591402023736, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555633, + "timestamp": 1591402013, + "timestampms": 1591402013590, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555627, + "timestamp": 1591402003, + "timestampms": 1591402003445, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555619, + "timestamp": 1591401993, + "timestampms": 1591401993297, + "type": "buy" + }, + { + "amount": "0.489786", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555458, + "timestamp": 1591401983, + "timestampms": 1591401983795, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555377, + "timestamp": 1591401983, + "timestampms": 1591401983154, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555341, + "timestamp": 1591401972, + "timestampms": 1591401972916, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555334, + "timestamp": 1591401962, + "timestampms": 1591401962775, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555327, + "timestamp": 1591401952, + "timestampms": 1591401952628, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555319, + "timestamp": 1591401942, + "timestampms": 1591401942466, + "type": "buy" + }, + { + "amount": "0.000214", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555312, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.000893", + "exchange": "gemini", + "price": "9576.28", + "tid": 607555310, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.000893", + "exchange": "gemini", + "price": "9576.28", + "tid": 607555308, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.0000244", + "exchange": "gemini", + "price": "9571.65", + "tid": 607555146, + "timestamp": 1591401922, + "timestampms": 1591401922147, + "type": "sell" + }, + { + "amount": "0.0008145", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555138, + "timestamp": 1591401922, + "timestampms": 1591401922121, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555110, + "timestamp": 1591401911, + "timestampms": 1591401911975, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555103, + "timestamp": 1591401901, + "timestampms": 1591401901829, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555096, + "timestamp": 1591401891, + "timestampms": 1591401891684, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555090, + "timestamp": 1591401881, + "timestampms": 1591401881540, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555082, + "timestamp": 1591401871, + "timestampms": 1591401871392, + "type": "buy" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554960, + "timestamp": 1591401861, + "timestampms": 1591401861706, + "type": "buy" + }, + { + "amount": "0.603", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554955, + "timestamp": 1591401861, + "timestampms": 1591401861682, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554950, + "timestamp": 1591401861, + "timestampms": 1591401861656, + "type": "buy" + }, + { + "amount": "0.613", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554945, + "timestamp": 1591401861, + "timestampms": 1591401861632, + "type": "buy" + }, + { + "amount": "0.108436", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554937, + "timestamp": 1591401861, + "timestampms": 1591401861608, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554929, + "timestamp": 1591401861, + "timestampms": 1591401861582, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554885, + "timestamp": 1591401861, + "timestampms": 1591401861253, + "type": "buy" + }, + { + "amount": "0.253645", + "exchange": "gemini", + "price": "9572.78", + "tid": 607554828, + "timestamp": 1591401860, + "timestampms": 1591401860909, + "type": "buy" + }, + { + "amount": "0.246355", + "exchange": "gemini", + "price": "9572.78", + "tid": 607554823, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.32042", + "exchange": "gemini", + "price": "9572.77", + "tid": 607554821, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.046225", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554819, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.108436", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554814, + "timestamp": 1591401860, + "timestampms": 1591401860858, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554807, + "timestamp": 1591401851, + "timestampms": 1591401851121, + "type": "buy" + }, + { + "amount": "0.001409", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554800, + "timestamp": 1591401840, + "timestampms": 1591401840976, + "type": "buy" + }, + { + "amount": "0.000591", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554798, + "timestamp": 1591401840, + "timestampms": 1591401840976, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554791, + "timestamp": 1591401830, + "timestampms": 1591401830835, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554785, + "timestamp": 1591401820, + "timestampms": 1591401820659, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554778, + "timestamp": 1591401810, + "timestampms": 1591401810515, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.82", + "tid": 607554615, + "timestamp": 1591401800, + "timestampms": 1591401800338, + "type": "sell" + }, + { + "amount": "0.99239", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554607, + "timestamp": 1591401800, + "timestampms": 1591401800302, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554602, + "timestamp": 1591401800, + "timestampms": 1591401800273, + "type": "sell" + }, + { + "amount": "0.32042", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554597, + "timestamp": 1591401800, + "timestampms": 1591401800247, + "type": "sell" + }, + { + "amount": "0.15807", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554592, + "timestamp": 1591401800, + "timestampms": 1591401800222, + "type": "sell" + }, + { + "amount": "0.00792", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554587, + "timestamp": 1591401800, + "timestampms": 1591401800198, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554520, + "timestamp": 1591401790, + "timestampms": 1591401790181, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554513, + "timestamp": 1591401780, + "timestampms": 1591401780049, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554507, + "timestamp": 1591401769, + "timestampms": 1591401769871, + "type": "sell" + }, + { + "amount": "0.000971", + "exchange": "gemini", + "price": "9577.43", + "tid": 607554501, + "timestamp": 1591401759, + "timestampms": 1591401759697, + "type": "buy" + }, + { + "amount": "0.001029", + "exchange": "gemini", + "price": "9577.43", + "tid": 607554499, + "timestamp": 1591401759, + "timestampms": 1591401759697, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554491, + "timestamp": 1591401749, + "timestampms": 1591401749525, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.73", + "tid": 607554389, + "timestamp": 1591401739, + "timestampms": 1591401739377, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554238, + "timestamp": 1591401729, + "timestampms": 1591401729237, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554232, + "timestamp": 1591401719, + "timestampms": 1591401719078, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554225, + "timestamp": 1591401708, + "timestampms": 1591401708928, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554218, + "timestamp": 1591401698, + "timestampms": 1591401698711, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554211, + "timestamp": 1591401688, + "timestampms": 1591401688541, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554145, + "timestamp": 1591401678, + "timestampms": 1591401678352, + "type": "buy" + }, + { + "amount": "0.016365", + "exchange": "gemini", + "price": "9602.93", + "tid": 607554062, + "timestamp": 1591401677, + "timestampms": 1591401677758, + "type": "sell" + }, + { + "amount": "0.8", + "exchange": "gemini", + "price": "9603.31", + "tid": 607554060, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9604.18", + "tid": 607554058, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9605.71", + "tid": 607554056, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.00052", + "exchange": "gemini", + "price": "9607.78", + "tid": 607554054, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.102932", + "exchange": "gemini", + "price": "9607.79", + "tid": 607554052, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "1.102967", + "exchange": "gemini", + "price": "9608.00", + "tid": 607554050, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.105302", + "exchange": "gemini", + "price": "9608.01", + "tid": 607554048, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9608.01", + "tid": 607553987, + "timestamp": 1591401668, + "timestampms": 1591401668204, + "type": "sell" + }, + { + "amount": "0.000408", + "exchange": "gemini", + "price": "9608.01", + "tid": 607553980, + "timestamp": 1591401658, + "timestampms": 1591401658050, + "type": "sell" + }, + { + "amount": "0.001592", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553978, + "timestamp": 1591401658, + "timestampms": 1591401658050, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553972, + "timestamp": 1591401647, + "timestampms": 1591401647914, + "type": "sell" + }, + { + "amount": "0.001166", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553966, + "timestamp": 1591401637, + "timestampms": 1591401637768, + "type": "sell" + }, + { + "amount": "0.000834", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553964, + "timestamp": 1591401637, + "timestampms": 1591401637768, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553956, + "timestamp": 1591401627, + "timestampms": 1591401627618, + "type": "sell" + }, + { + "amount": "0.001924", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553908, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.000038", + "exchange": "gemini", + "price": "9611.70", + "tid": 607553906, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.000038", + "exchange": "gemini", + "price": "9611.70", + "tid": 607553904, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.204253", + "exchange": "gemini", + "price": "9614.81", + "tid": 607553797, + "timestamp": 1591401616, + "timestampms": 1591401616739, + "type": "sell" + }, + { + "amount": "0.793747", + "exchange": "gemini", + "price": "9614.81", + "tid": 607553792, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9616.60", + "tid": 607553790, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.553", + "exchange": "gemini", + "price": "9616.71", + "tid": 607553788, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.95", + "exchange": "gemini", + "price": "9617.20", + "tid": 607553786, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.489653", + "exchange": "gemini", + "price": "9617.71", + "tid": 607553784, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.457347", + "exchange": "gemini", + "price": "9617.71", + "tid": 607553779, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.103958", + "exchange": "gemini", + "price": "9619.31", + "tid": 607553777, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9621.20", + "tid": 607553775, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.328695", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553773, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.000637", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553768, + "timestamp": 1591401616, + "timestampms": 1591401616665, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553701, + "timestamp": 1591401607, + "timestampms": 1591401607318, + "type": "sell" + } + ], + "queryString": "limit_trades=500\u0026since=1591401600", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "0.0002916", + "exchange": "gemini", + "price": "9593.65", + "tid": 607568549, + "timestamp": 1591404856, + "timestampms": 1591404856618, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.81", + "tid": 607568428, + "timestamp": 1591404846, + "timestampms": 1591404846471, + "type": "buy" + }, + { + "amount": "0.0002088", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568421, + "timestamp": 1591404836, + "timestampms": 1591404836328, + "type": "sell" + }, + { + "amount": "0.0006945", + "exchange": "gemini", + "price": "9593.81", + "tid": 607568416, + "timestamp": 1591404836, + "timestampms": 1591404836302, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568409, + "timestamp": 1591404826, + "timestampms": 1591404826149, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568403, + "timestamp": 1591404816, + "timestampms": 1591404816000, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568397, + "timestamp": 1591404805, + "timestampms": 1591404805856, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9593.32", + "tid": 607568325, + "timestamp": 1591404795, + "timestampms": 1591404795719, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568194, + "timestamp": 1591404785, + "timestampms": 1591404785573, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568188, + "timestamp": 1591404775, + "timestampms": 1591404775428, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568182, + "timestamp": 1591404765, + "timestampms": 1591404765296, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568176, + "timestamp": 1591404755, + "timestampms": 1591404755158, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9600.06", + "tid": 607568169, + "timestamp": 1591404745, + "timestampms": 1591404745019, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.46", + "tid": 607568123, + "timestamp": 1591404734, + "timestampms": 1591404734862, + "type": "buy" + }, + { + "amount": "0.061678", + "exchange": "gemini", + "price": "9588.46", + "tid": 607567994, + "timestamp": 1591404734, + "timestampms": 1591404734257, + "type": "buy" + }, + { + "amount": "1.7734732", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567924, + "timestamp": 1591404733, + "timestampms": 1591404733737, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567919, + "timestamp": 1591404733, + "timestampms": 1591404733713, + "type": "buy" + }, + { + "amount": "0.029082", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567914, + "timestamp": 1591404733, + "timestampms": 1591404733690, + "type": "buy" + }, + { + "amount": "0.035174", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567909, + "timestamp": 1591404733, + "timestampms": 1591404733667, + "type": "buy" + }, + { + "amount": "0.03108", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567904, + "timestamp": 1591404733, + "timestampms": 1591404733643, + "type": "buy" + }, + { + "amount": "0.0311908", + "exchange": "gemini", + "price": "9586.90", + "tid": 607567899, + "timestamp": 1591404733, + "timestampms": 1591404733617, + "type": "buy" + }, + { + "amount": "0.1688092", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567897, + "timestamp": 1591404733, + "timestampms": 1591404733617, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567890, + "timestamp": 1591404724, + "timestampms": 1591404724719, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567883, + "timestamp": 1591404714, + "timestampms": 1591404714575, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567876, + "timestamp": 1591404704, + "timestampms": 1591404704420, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567870, + "timestamp": 1591404694, + "timestampms": 1591404694283, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567864, + "timestamp": 1591404684, + "timestampms": 1591404684139, + "type": "buy" + }, + { + "amount": "0.0006352", + "exchange": "gemini", + "price": "9583.20", + "tid": 607567840, + "timestamp": 1591404673, + "timestampms": 1591404673975, + "type": "sell" + }, + { + "amount": "0.0001298", + "exchange": "gemini", + "price": "9586.02", + "tid": 607567832, + "timestamp": 1591404673, + "timestampms": 1591404673946, + "type": "buy" + }, + { + "amount": "1.345907", + "exchange": "gemini", + "price": "9588.08", + "tid": 607567686, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.02826", + "exchange": "gemini", + "price": "9588.09", + "tid": 607567684, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.9816", + "exchange": "gemini", + "price": "9588.72", + "tid": 607567682, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.023172", + "exchange": "gemini", + "price": "9588.73", + "tid": 607567680, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.021061", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567678, + "timestamp": 1591404673, + "timestampms": 1591404673001, + "type": "sell" + }, + { + "amount": "0.178939", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567673, + "timestamp": 1591404672, + "timestampms": 1591404672977, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567606, + "timestamp": 1591404663, + "timestampms": 1591404663783, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567600, + "timestamp": 1591404653, + "timestampms": 1591404653637, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567594, + "timestamp": 1591404643, + "timestampms": 1591404643497, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567586, + "timestamp": 1591404633, + "timestampms": 1591404633356, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567580, + "timestamp": 1591404623, + "timestampms": 1591404623188, + "type": "buy" + }, + { + "amount": "0.0003915", + "exchange": "gemini", + "price": "9589.15", + "tid": 607567574, + "timestamp": 1591404613, + "timestampms": 1591404613023, + "type": "sell" + }, + { + "amount": "0.0004328", + "exchange": "gemini", + "price": "9596.10", + "tid": 607567566, + "timestamp": 1591404612, + "timestampms": 1591404612995, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567382, + "timestamp": 1591404602, + "timestampms": 1591404602843, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567375, + "timestamp": 1591404592, + "timestampms": 1591404592697, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567368, + "timestamp": 1591404582, + "timestampms": 1591404582565, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567361, + "timestamp": 1591404572, + "timestampms": 1591404572384, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567355, + "timestamp": 1591404562, + "timestampms": 1591404562233, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9594.37", + "tid": 607567348, + "timestamp": 1591404552, + "timestampms": 1591404552063, + "type": "buy" + }, + { + "amount": "0.198334", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567149, + "timestamp": 1591404550, + "timestampms": 1591404550712, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567068, + "timestamp": 1591404541, + "timestampms": 1591404541922, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567061, + "timestamp": 1591404531, + "timestampms": 1591404531777, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567055, + "timestamp": 1591404521, + "timestampms": 1591404521641, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567048, + "timestamp": 1591404511, + "timestampms": 1591404511468, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567042, + "timestamp": 1591404501, + "timestampms": 1591404501328, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.04", + "tid": 607567035, + "timestamp": 1591404491, + "timestampms": 1591404491188, + "type": "buy" + }, + { + "amount": "0.1814453", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566854, + "timestamp": 1591404489, + "timestampms": 1591404489598, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566785, + "timestamp": 1591404481, + "timestampms": 1591404481038, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566778, + "timestamp": 1591404470, + "timestampms": 1591404470894, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566772, + "timestamp": 1591404460, + "timestampms": 1591404460754, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566766, + "timestamp": 1591404450, + "timestampms": 1591404450595, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566759, + "timestamp": 1591404440, + "timestampms": 1591404440451, + "type": "buy" + }, + { + "amount": "0.0005769", + "exchange": "gemini", + "price": "9571.23", + "tid": 607566752, + "timestamp": 1591404430, + "timestampms": 1591404430283, + "type": "sell" + }, + { + "amount": "0.0001397", + "exchange": "gemini", + "price": "9577.93", + "tid": 607566747, + "timestamp": 1591404430, + "timestampms": 1591404430257, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566500, + "timestamp": 1591404420, + "timestampms": 1591404420101, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566494, + "timestamp": 1591404409, + "timestampms": 1591404409957, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566488, + "timestamp": 1591404399, + "timestampms": 1591404399816, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566481, + "timestamp": 1591404389, + "timestampms": 1591404389679, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566475, + "timestamp": 1591404379, + "timestampms": 1591404379537, + "type": "sell" + }, + { + "amount": "0.0002322", + "exchange": "gemini", + "price": "9575.50", + "tid": 607566468, + "timestamp": 1591404369, + "timestampms": 1591404369398, + "type": "sell" + }, + { + "amount": "0.0001925", + "exchange": "gemini", + "price": "9578.76", + "tid": 607566463, + "timestamp": 1591404369, + "timestampms": 1591404369369, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566217, + "timestamp": 1591404359, + "timestampms": 1591404359231, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566210, + "timestamp": 1591404349, + "timestampms": 1591404349088, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566203, + "timestamp": 1591404338, + "timestampms": 1591404338881, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566197, + "timestamp": 1591404328, + "timestampms": 1591404328732, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566191, + "timestamp": 1591404318, + "timestampms": 1591404318587, + "type": "buy" + }, + { + "amount": "0.0009253", + "exchange": "gemini", + "price": "9574.55", + "tid": 607566184, + "timestamp": 1591404308, + "timestampms": 1591404308416, + "type": "sell" + }, + { + "amount": "0.0009995", + "exchange": "gemini", + "price": "9580.26", + "tid": 607566179, + "timestamp": 1591404308, + "timestampms": 1591404308391, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565932, + "timestamp": 1591404298, + "timestampms": 1591404298242, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565926, + "timestamp": 1591404288, + "timestampms": 1591404288101, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565920, + "timestamp": 1591404277, + "timestampms": 1591404277964, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565913, + "timestamp": 1591404267, + "timestampms": 1591404267818, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9571.60", + "tid": 607565907, + "timestamp": 1591404257, + "timestampms": 1591404257649, + "type": "sell" + }, + { + "amount": "0.0005395", + "exchange": "gemini", + "price": "9571.60", + "tid": 607565900, + "timestamp": 1591404247, + "timestampms": 1591404247518, + "type": "sell" + }, + { + "amount": "0.0007753", + "exchange": "gemini", + "price": "9576.98", + "tid": 607565895, + "timestamp": 1591404247, + "timestampms": 1591404247489, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565671, + "timestamp": 1591404237, + "timestampms": 1591404237349, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565664, + "timestamp": 1591404227, + "timestampms": 1591404227210, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565658, + "timestamp": 1591404217, + "timestampms": 1591404217073, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565652, + "timestamp": 1591404206, + "timestampms": 1591404206938, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565646, + "timestamp": 1591404196, + "timestampms": 1591404196773, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9575.70", + "tid": 607565639, + "timestamp": 1591404186, + "timestampms": 1591404186598, + "type": "buy" + }, + { + "amount": "0.1938328", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565455, + "timestamp": 1591404184, + "timestampms": 1591404184045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565377, + "timestamp": 1591404176, + "timestampms": 1591404176426, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565371, + "timestamp": 1591404166, + "timestampms": 1591404166248, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565365, + "timestamp": 1591404156, + "timestampms": 1591404156076, + "type": "sell" + }, + { + "amount": "0.000403", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565358, + "timestamp": 1591404145, + "timestampms": 1591404145937, + "type": "sell" + }, + { + "amount": "0.0000897", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565353, + "timestamp": 1591404145, + "timestampms": 1591404145912, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565346, + "timestamp": 1591404135, + "timestampms": 1591404135772, + "type": "buy" + }, + { + "amount": "0.0001711", + "exchange": "gemini", + "price": "9562.39", + "tid": 607565339, + "timestamp": 1591404125, + "timestampms": 1591404125641, + "type": "sell" + }, + { + "amount": "0.0002345", + "exchange": "gemini", + "price": "9568.83", + "tid": 607565334, + "timestamp": 1591404125, + "timestampms": 1591404125613, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565147, + "timestamp": 1591404115, + "timestampms": 1591404115468, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565140, + "timestamp": 1591404105, + "timestampms": 1591404105316, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565134, + "timestamp": 1591404095, + "timestampms": 1591404095175, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565128, + "timestamp": 1591404085, + "timestampms": 1591404085041, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565122, + "timestamp": 1591404074, + "timestampms": 1591404074879, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.07", + "tid": 607565115, + "timestamp": 1591404064, + "timestampms": 1591404064740, + "type": "buy" + }, + { + "amount": "0.09192", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564957, + "timestamp": 1591404061, + "timestampms": 1591404061872, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564890, + "timestamp": 1591404054, + "timestampms": 1591404054591, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564884, + "timestamp": 1591404044, + "timestampms": 1591404044425, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564877, + "timestamp": 1591404034, + "timestampms": 1591404034246, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564870, + "timestamp": 1591404024, + "timestampms": 1591404024079, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564864, + "timestamp": 1591404013, + "timestampms": 1591404013899, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9557.45", + "tid": 607564857, + "timestamp": 1591404003, + "timestampms": 1591404003723, + "type": "buy" + }, + { + "amount": "1.5550442", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564721, + "timestamp": 1591404000, + "timestampms": 1591404000815, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564713, + "timestamp": 1591404000, + "timestampms": 1591404000786, + "type": "buy" + }, + { + "amount": "0.9904", + "exchange": "gemini", + "price": "9538.13", + "tid": 607564705, + "timestamp": 1591404000, + "timestampms": 1591404000760, + "type": "buy" + }, + { + "amount": "3.558782", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564656, + "timestamp": 1591404000, + "timestampms": 1591404000351, + "type": "buy" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564651, + "timestamp": 1591404000, + "timestampms": 1591404000328, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564646, + "timestamp": 1591404000, + "timestampms": 1591404000305, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564641, + "timestamp": 1591404000, + "timestampms": 1591404000282, + "type": "buy" + }, + { + "amount": "0.173295", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564636, + "timestamp": 1591404000, + "timestampms": 1591404000259, + "type": "buy" + }, + { + "amount": "0.085851", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564631, + "timestamp": 1591404000, + "timestampms": 1591404000235, + "type": "buy" + }, + { + "amount": "0.172072", + "exchange": "gemini", + "price": "9537.23", + "tid": 607564626, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "2.7", + "exchange": "gemini", + "price": "9535.55", + "tid": 607564624, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "0.112207", + "exchange": "gemini", + "price": "9535.54", + "tid": 607564622, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "1.715721", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564620, + "timestamp": 1591404000, + "timestampms": 1591404000209, + "type": "buy" + }, + { + "amount": "0.9795", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564615, + "timestamp": 1591404000, + "timestampms": 1591404000186, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564610, + "timestamp": 1591404000, + "timestampms": 1591404000162, + "type": "buy" + }, + { + "amount": "0.804779", + "exchange": "gemini", + "price": "9535.47", + "tid": 607564605, + "timestamp": 1591404000, + "timestampms": 1591404000136, + "type": "buy" + }, + { + "amount": "0.094457", + "exchange": "gemini", + "price": "9535.46", + "tid": 607564603, + "timestamp": 1591404000, + "timestampms": 1591404000135, + "type": "buy" + }, + { + "amount": "0.091164", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564601, + "timestamp": 1591404000, + "timestampms": 1591404000135, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564595, + "timestamp": 1591403993, + "timestampms": 1591403993583, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564588, + "timestamp": 1591403983, + "timestampms": 1591403983430, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564582, + "timestamp": 1591403973, + "timestampms": 1591403973279, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564576, + "timestamp": 1591403963, + "timestampms": 1591403963041, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564570, + "timestamp": 1591403952, + "timestampms": 1591403952900, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9535.45", + "tid": 607564563, + "timestamp": 1591403942, + "timestampms": 1591403942758, + "type": "buy" + }, + { + "amount": "0.2545558", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564440, + "timestamp": 1591403939, + "timestampms": 1591403939725, + "type": "sell" + }, + { + "amount": "4.7", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564432, + "timestamp": 1591403939, + "timestampms": 1591403939699, + "type": "sell" + }, + { + "amount": "0.0271442", + "exchange": "gemini", + "price": "9538.76", + "tid": 607564424, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9540.52", + "tid": 607564422, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9541.14", + "tid": 607564420, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "2.1628558", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564418, + "timestamp": 1591403939, + "timestampms": 1591403939675, + "type": "sell" + }, + { + "amount": "0.112207", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564407, + "timestamp": 1591403939, + "timestampms": 1591403939647, + "type": "sell" + }, + { + "amount": "2.4249372", + "exchange": "gemini", + "price": "9543.00", + "tid": 607564402, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9543.74", + "tid": 607564400, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.9971", + "exchange": "gemini", + "price": "9544.24", + "tid": 607564398, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.0779628", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564396, + "timestamp": 1591403939, + "timestampms": 1591403939622, + "type": "sell" + }, + { + "amount": "0.094457", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564391, + "timestamp": 1591403939, + "timestampms": 1591403939598, + "type": "sell" + }, + { + "amount": "0.0275802", + "exchange": "gemini", + "price": "9546.26", + "tid": 607564386, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.041524", + "exchange": "gemini", + "price": "9546.27", + "tid": 607564384, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.0340598", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564382, + "timestamp": 1591403939, + "timestampms": 1591403939572, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564320, + "timestamp": 1591403932, + "timestampms": 1591403932613, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564312, + "timestamp": 1591403922, + "timestampms": 1591403922469, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564305, + "timestamp": 1591403912, + "timestampms": 1591403912313, + "type": "sell" + }, + { + "amount": "0.0014642", + "exchange": "gemini", + "price": "9546.28", + "tid": 607564299, + "timestamp": 1591403902, + "timestampms": 1591403902171, + "type": "sell" + }, + { + "amount": "0.0005358", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564297, + "timestamp": 1591403902, + "timestampms": 1591403902171, + "type": "sell" + }, + { + "amount": "0.0004642", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564290, + "timestamp": 1591403892, + "timestampms": 1591403892021, + "type": "sell" + }, + { + "amount": "0.000236", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564288, + "timestamp": 1591403892, + "timestampms": 1591403892021, + "type": "sell" + }, + { + "amount": "0.0000285", + "exchange": "gemini", + "price": "9551.03", + "tid": 607564283, + "timestamp": 1591403891, + "timestampms": 1591403891994, + "type": "buy" + }, + { + "amount": "0.000764", + "exchange": "gemini", + "price": "9548.83", + "tid": 607564277, + "timestamp": 1591403881, + "timestampms": 1591403881842, + "type": "sell" + }, + { + "amount": "0.0005176", + "exchange": "gemini", + "price": "9551.03", + "tid": 607564272, + "timestamp": 1591403881, + "timestampms": 1591403881807, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564048, + "timestamp": 1591403871, + "timestampms": 1591403871634, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564042, + "timestamp": 1591403861, + "timestampms": 1591403861464, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564036, + "timestamp": 1591403851, + "timestampms": 1591403851320, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9550.24", + "tid": 607564030, + "timestamp": 1591403841, + "timestampms": 1591403841152, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9548.22", + "tid": 607564023, + "timestamp": 1591403831, + "timestampms": 1591403831004, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9548.22", + "tid": 607564017, + "timestamp": 1591403820, + "timestampms": 1591403820847, + "type": "sell" + }, + { + "amount": "0.09552", + "exchange": "gemini", + "price": "9550.68", + "tid": 607563954, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.093063", + "exchange": "gemini", + "price": "9550.69", + "tid": 607563952, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.093063", + "exchange": "gemini", + "price": "9550.70", + "tid": 607563950, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "9550.71", + "tid": 607563948, + "timestamp": 1591403817, + "timestampms": 1591403817932, + "type": "sell" + }, + { + "amount": "0.273359", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563850, + "timestamp": 1591403817, + "timestampms": 1591403817384, + "type": "sell" + }, + { + "amount": "0.208861", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563845, + "timestamp": 1591403817, + "timestampms": 1591403817360, + "type": "sell" + }, + { + "amount": "0.01778", + "exchange": "gemini", + "price": "9558.12", + "tid": 607563840, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9558.14", + "tid": 607563838, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.17222", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563836, + "timestamp": 1591403817, + "timestampms": 1591403817337, + "type": "sell" + }, + { + "amount": "0.018562", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563831, + "timestamp": 1591403817, + "timestampms": 1591403817312, + "type": "sell" + }, + { + "amount": "0.009218", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563826, + "timestamp": 1591403817, + "timestampms": 1591403817287, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563763, + "timestamp": 1591403810, + "timestampms": 1591403810702, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563757, + "timestamp": 1591403800, + "timestampms": 1591403800558, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563749, + "timestamp": 1591403790, + "timestampms": 1591403790419, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563743, + "timestamp": 1591403780, + "timestampms": 1591403780275, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9560.12", + "tid": 607563736, + "timestamp": 1591403770, + "timestampms": 1591403770131, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607563730, + "timestamp": 1591403759, + "timestampms": 1591403759974, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563491, + "timestamp": 1591403749, + "timestampms": 1591403749830, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563485, + "timestamp": 1591403739, + "timestampms": 1591403739675, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563477, + "timestamp": 1591403729, + "timestampms": 1591403729529, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563471, + "timestamp": 1591403719, + "timestampms": 1591403719380, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563464, + "timestamp": 1591403709, + "timestampms": 1591403709204, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.99", + "tid": 607563458, + "timestamp": 1591403699, + "timestampms": 1591403699047, + "type": "buy" + }, + { + "amount": "0.016213", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563216, + "timestamp": 1591403694, + "timestampms": 1591403694631, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563210, + "timestamp": 1591403688, + "timestampms": 1591403688883, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563204, + "timestamp": 1591403678, + "timestampms": 1591403678743, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563196, + "timestamp": 1591403668, + "timestampms": 1591403668586, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563190, + "timestamp": 1591403658, + "timestampms": 1591403658442, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563183, + "timestamp": 1591403648, + "timestampms": 1591403648304, + "type": "buy" + }, + { + "amount": "0.0006749", + "exchange": "gemini", + "price": "9569.71", + "tid": 607563177, + "timestamp": 1591403638, + "timestampms": 1591403638149, + "type": "sell" + }, + { + "amount": "0.0005197", + "exchange": "gemini", + "price": "9569.72", + "tid": 607563172, + "timestamp": 1591403638, + "timestampms": 1591403638117, + "type": "buy" + }, + { + "amount": "0.047256", + "exchange": "gemini", + "price": "9572.81", + "tid": 607562996, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.040922", + "exchange": "gemini", + "price": "9572.83", + "tid": 607562994, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.030111", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562992, + "timestamp": 1591403633, + "timestampms": 1591403633899, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562927, + "timestamp": 1591403627, + "timestampms": 1591403627973, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562921, + "timestamp": 1591403617, + "timestampms": 1591403617803, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562914, + "timestamp": 1591403607, + "timestampms": 1591403607657, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562908, + "timestamp": 1591403597, + "timestampms": 1591403597509, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562901, + "timestamp": 1591403587, + "timestampms": 1591403587367, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.84", + "tid": 607562894, + "timestamp": 1591403577, + "timestampms": 1591403577178, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562832, + "timestamp": 1591403573, + "timestampms": 1591403573314, + "type": "sell" + }, + { + "amount": "0.0002187", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562646, + "timestamp": 1591403567, + "timestampms": 1591403567031, + "type": "sell" + }, + { + "amount": "0.0004303", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562641, + "timestamp": 1591403567, + "timestampms": 1591403567002, + "type": "buy" + }, + { + "amount": "0.0004764", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562635, + "timestamp": 1591403556, + "timestampms": 1591403556865, + "type": "sell" + }, + { + "amount": "0.0000585", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562630, + "timestamp": 1591403556, + "timestampms": 1591403556837, + "type": "buy" + }, + { + "amount": "0.0003351", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562622, + "timestamp": 1591403546, + "timestampms": 1591403546679, + "type": "sell" + }, + { + "amount": "0.0008963", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562617, + "timestamp": 1591403546, + "timestampms": 1591403546652, + "type": "buy" + }, + { + "amount": "0.00029", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562611, + "timestamp": 1591403536, + "timestampms": 1591403536489, + "type": "sell" + }, + { + "amount": "0.0009719", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562606, + "timestamp": 1591403536, + "timestampms": 1591403536463, + "type": "buy" + }, + { + "amount": "0.0007671", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562599, + "timestamp": 1591403526, + "timestampms": 1591403526320, + "type": "sell" + }, + { + "amount": "0.0004812", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562594, + "timestamp": 1591403526, + "timestampms": 1591403526293, + "type": "buy" + }, + { + "amount": "0.000408", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562587, + "timestamp": 1591403516, + "timestampms": 1591403516146, + "type": "sell" + }, + { + "amount": "0.0009649", + "exchange": "gemini", + "price": "9582.67", + "tid": 607562582, + "timestamp": 1591403516, + "timestampms": 1591403516117, + "type": "buy" + }, + { + "amount": "0.0009456", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562335, + "timestamp": 1591403505, + "timestampms": 1591403505931, + "type": "sell" + }, + { + "amount": "0.0005362", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562330, + "timestamp": 1591403505, + "timestampms": 1591403505904, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562324, + "timestamp": 1591403495, + "timestampms": 1591403495761, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562317, + "timestamp": 1591403485, + "timestampms": 1591403485618, + "type": "buy" + }, + { + "amount": "0.0002386", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562311, + "timestamp": 1591403475, + "timestampms": 1591403475455, + "type": "sell" + }, + { + "amount": "0.0001172", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562306, + "timestamp": 1591403475, + "timestampms": 1591403475429, + "type": "buy" + }, + { + "amount": "0.000214", + "exchange": "gemini", + "price": "9579.52", + "tid": 607562298, + "timestamp": 1591403465, + "timestampms": 1591403465287, + "type": "sell" + }, + { + "amount": "0.0006639", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562293, + "timestamp": 1591403465, + "timestampms": 1591403465261, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.96", + "tid": 607562287, + "timestamp": 1591403455, + "timestampms": 1591403455126, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562041, + "timestamp": 1591403444, + "timestampms": 1591403444989, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562034, + "timestamp": 1591403434, + "timestampms": 1591403434852, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562027, + "timestamp": 1591403424, + "timestampms": 1591403424702, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562020, + "timestamp": 1591403414, + "timestampms": 1591403414550, + "type": "sell" + }, + { + "amount": "0.0007981", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562013, + "timestamp": 1591403404, + "timestampms": 1591403404404, + "type": "sell" + }, + { + "amount": "0.0008822", + "exchange": "gemini", + "price": "9588.51", + "tid": 607562008, + "timestamp": 1591403404, + "timestampms": 1591403404379, + "type": "buy" + }, + { + "amount": "0.000424", + "exchange": "gemini", + "price": "9581.77", + "tid": 607562001, + "timestamp": 1591403394, + "timestampms": 1591403394242, + "type": "sell" + }, + { + "amount": "0.0007653", + "exchange": "gemini", + "price": "9588.51", + "tid": 607561996, + "timestamp": 1591403394, + "timestampms": 1591403394217, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561749, + "timestamp": 1591403384, + "timestampms": 1591403384076, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561743, + "timestamp": 1591403373, + "timestampms": 1591403373932, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561736, + "timestamp": 1591403363, + "timestampms": 1591403363787, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.56", + "tid": 607561730, + "timestamp": 1591403353, + "timestampms": 1591403353618, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.91", + "tid": 607561723, + "timestamp": 1591403343, + "timestampms": 1591403343474, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.91", + "tid": 607561717, + "timestamp": 1591403333, + "timestampms": 1591403333305, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561477, + "timestamp": 1591403323, + "timestampms": 1591403323168, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561469, + "timestamp": 1591403312, + "timestampms": 1591403312989, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561462, + "timestamp": 1591403302, + "timestampms": 1591403302826, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561456, + "timestamp": 1591403292, + "timestampms": 1591403292681, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.03", + "tid": 607561448, + "timestamp": 1591403282, + "timestampms": 1591403282520, + "type": "sell" + }, + { + "amount": "0.001592", + "exchange": "gemini", + "price": "9592.05", + "tid": 607561440, + "timestamp": 1591403272, + "timestampms": 1591403272375, + "type": "buy" + }, + { + "amount": "0.000204", + "exchange": "gemini", + "price": "9588.48", + "tid": 607561438, + "timestamp": 1591403272, + "timestampms": 1591403272374, + "type": "buy" + }, + { + "amount": "0.000204", + "exchange": "gemini", + "price": "9588.48", + "tid": 607561436, + "timestamp": 1591403272, + "timestampms": 1591403272374, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561190, + "timestamp": 1591403262, + "timestampms": 1591403262231, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561183, + "timestamp": 1591403252, + "timestampms": 1591403252090, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561177, + "timestamp": 1591403241, + "timestampms": 1591403241947, + "type": "buy" + }, + { + "amount": "0.0000292", + "exchange": "gemini", + "price": "9586.80", + "tid": 607561170, + "timestamp": 1591403231, + "timestampms": 1591403231777, + "type": "sell" + }, + { + "amount": "0.0009821", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561165, + "timestamp": 1591403231, + "timestampms": 1591403231741, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561158, + "timestamp": 1591403221, + "timestampms": 1591403221561, + "type": "buy" + }, + { + "amount": "0.0000987", + "exchange": "gemini", + "price": "9586.80", + "tid": 607561151, + "timestamp": 1591403211, + "timestampms": 1591403211383, + "type": "sell" + }, + { + "amount": "0.0009426", + "exchange": "gemini", + "price": "9590.27", + "tid": 607561146, + "timestamp": 1591403211, + "timestampms": 1591403211358, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560900, + "timestamp": 1591403201, + "timestampms": 1591403201204, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560892, + "timestamp": 1591403191, + "timestampms": 1591403191066, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.78", + "tid": 607560886, + "timestamp": 1591403180, + "timestampms": 1591403180919, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9586.78", + "tid": 607560879, + "timestamp": 1591403170, + "timestampms": 1591403170773, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560872, + "timestamp": 1591403160, + "timestampms": 1591403160632, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.78", + "tid": 607560865, + "timestamp": 1591403150, + "timestampms": 1591403150478, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560643, + "timestamp": 1591403140, + "timestampms": 1591403140334, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560636, + "timestamp": 1591403130, + "timestampms": 1591403130189, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.84", + "tid": 607560629, + "timestamp": 1591403120, + "timestampms": 1591403120037, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.84", + "tid": 607560622, + "timestamp": 1591403109, + "timestampms": 1591403109901, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560615, + "timestamp": 1591403099, + "timestampms": 1591403099753, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.73", + "tid": 607560609, + "timestamp": 1591403089, + "timestampms": 1591403089621, + "type": "buy" + }, + { + "amount": "0.049741", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560427, + "timestamp": 1591403083, + "timestampms": 1591403083750, + "type": "buy" + }, + { + "amount": "0.140535", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560419, + "timestamp": 1591403083, + "timestampms": 1591403083724, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560354, + "timestamp": 1591403079, + "timestampms": 1591403079469, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560346, + "timestamp": 1591403069, + "timestampms": 1591403069242, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560339, + "timestamp": 1591403059, + "timestampms": 1591403059096, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560333, + "timestamp": 1591403048, + "timestampms": 1591403048954, + "type": "buy" + }, + { + "amount": "0.001724", + "exchange": "gemini", + "price": "9582.49", + "tid": 607560327, + "timestamp": 1591403038, + "timestampms": 1591403038792, + "type": "buy" + }, + { + "amount": "0.000276", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560325, + "timestamp": 1591403038, + "timestampms": 1591403038792, + "type": "buy" + }, + { + "amount": "0.000862", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560318, + "timestamp": 1591403028, + "timestampms": 1591403028651, + "type": "buy" + }, + { + "amount": "0.001138", + "exchange": "gemini", + "price": "9581.12", + "tid": 607560316, + "timestamp": 1591403028, + "timestampms": 1591403028651, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560075, + "timestamp": 1591403018, + "timestampms": 1591403018513, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560068, + "timestamp": 1591403008, + "timestampms": 1591403008372, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560062, + "timestamp": 1591402998, + "timestampms": 1591402998210, + "type": "sell" + }, + { + "amount": "0.0005549", + "exchange": "gemini", + "price": "9581.41", + "tid": 607560055, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.001138", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560053, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.0003071", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560051, + "timestamp": 1591402988, + "timestampms": 1591402988025, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560044, + "timestamp": 1591402977, + "timestampms": 1591402977892, + "type": "sell" + }, + { + "amount": "0.0006934", + "exchange": "gemini", + "price": "9577.65", + "tid": 607560038, + "timestamp": 1591402967, + "timestampms": 1591402967753, + "type": "sell" + }, + { + "amount": "0.0008309", + "exchange": "gemini", + "price": "9581.16", + "tid": 607560033, + "timestamp": 1591402967, + "timestampms": 1591402967728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559787, + "timestamp": 1591402957, + "timestampms": 1591402957585, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559779, + "timestamp": 1591402947, + "timestampms": 1591402947433, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559773, + "timestamp": 1591402937, + "timestampms": 1591402937292, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559766, + "timestamp": 1591402927, + "timestampms": 1591402927155, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559758, + "timestamp": 1591402917, + "timestampms": 1591402917014, + "type": "sell" + }, + { + "amount": "0.0003975", + "exchange": "gemini", + "price": "9574.11", + "tid": 607559751, + "timestamp": 1591402906, + "timestampms": 1591402906876, + "type": "sell" + }, + { + "amount": "0.0004107", + "exchange": "gemini", + "price": "9580.10", + "tid": 607559746, + "timestamp": 1591402906, + "timestampms": 1591402906849, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559506, + "timestamp": 1591402896, + "timestampms": 1591402896705, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559499, + "timestamp": 1591402886, + "timestampms": 1591402886564, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559493, + "timestamp": 1591402876, + "timestampms": 1591402876423, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559486, + "timestamp": 1591402866, + "timestampms": 1591402866273, + "type": "sell" + }, + { + "amount": "0.0003464", + "exchange": "gemini", + "price": "9577.13", + "tid": 607559479, + "timestamp": 1591402856, + "timestampms": 1591402856131, + "type": "sell" + }, + { + "amount": "0.0005546", + "exchange": "gemini", + "price": "9583.04", + "tid": 607559474, + "timestamp": 1591402856, + "timestampms": 1591402856102, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.04", + "tid": 607559468, + "timestamp": 1591402845, + "timestampms": 1591402845958, + "type": "buy" + }, + { + "amount": "0.041068", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559303, + "timestamp": 1591402839, + "timestampms": 1591402839358, + "type": "sell" + }, + { + "amount": "0.049136", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559295, + "timestamp": 1591402839, + "timestampms": 1591402839333, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559218, + "timestamp": 1591402835, + "timestampms": 1591402835798, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559210, + "timestamp": 1591402825, + "timestampms": 1591402825656, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559203, + "timestamp": 1591402815, + "timestampms": 1591402815498, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559196, + "timestamp": 1591402805, + "timestampms": 1591402805357, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559189, + "timestamp": 1591402795, + "timestampms": 1591402795216, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9583.05", + "tid": 607559182, + "timestamp": 1591402785, + "timestampms": 1591402785043, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607559002, + "timestamp": 1591402774, + "timestampms": 1591402774902, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558995, + "timestamp": 1591402764, + "timestampms": 1591402764757, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558989, + "timestamp": 1591402754, + "timestampms": 1591402754626, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558982, + "timestamp": 1591402744, + "timestampms": 1591402744487, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558976, + "timestamp": 1591402734, + "timestampms": 1591402734348, + "type": "buy" + }, + { + "amount": "0.001644", + "exchange": "gemini", + "price": "9591.12", + "tid": 607558970, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.000178", + "exchange": "gemini", + "price": "9587.81", + "tid": 607558968, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.000178", + "exchange": "gemini", + "price": "9587.81", + "tid": 607558966, + "timestamp": 1591402724, + "timestampms": 1591402724219, + "type": "buy" + }, + { + "amount": "0.389845", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558803, + "timestamp": 1591402717, + "timestampms": 1591402717175, + "type": "buy" + }, + { + "amount": "0.598155", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558795, + "timestamp": 1591402717, + "timestampms": 1591402717151, + "type": "buy" + }, + { + "amount": "4", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558787, + "timestamp": 1591402717, + "timestampms": 1591402717127, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558692, + "timestamp": 1591402714, + "timestampms": 1591402714077, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558684, + "timestamp": 1591402703, + "timestampms": 1591402703937, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558678, + "timestamp": 1591402693, + "timestampms": 1591402693794, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558671, + "timestamp": 1591402683, + "timestampms": 1591402683639, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558664, + "timestamp": 1591402673, + "timestampms": 1591402673488, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9576.68", + "tid": 607558657, + "timestamp": 1591402663, + "timestampms": 1591402663343, + "type": "buy" + }, + { + "amount": "0.188744", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558488, + "timestamp": 1591402656, + "timestampms": 1591402656027, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558404, + "timestamp": 1591402653, + "timestampms": 1591402653199, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558397, + "timestamp": 1591402643, + "timestampms": 1591402643061, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558391, + "timestamp": 1591402632, + "timestampms": 1591402632925, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558384, + "timestamp": 1591402622, + "timestampms": 1591402622788, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558378, + "timestamp": 1591402612, + "timestampms": 1591402612642, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.27", + "tid": 607558370, + "timestamp": 1591402602, + "timestampms": 1591402602467, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558122, + "timestamp": 1591402592, + "timestampms": 1591402592328, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558116, + "timestamp": 1591402582, + "timestampms": 1591402582181, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558109, + "timestamp": 1591402572, + "timestampms": 1591402572040, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558103, + "timestamp": 1591402561, + "timestampms": 1591402561895, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.10", + "tid": 607558095, + "timestamp": 1591402551, + "timestampms": 1591402551737, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.28", + "tid": 607558089, + "timestamp": 1591402541, + "timestampms": 1591402541578, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557848, + "timestamp": 1591402531, + "timestampms": 1591402531426, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557842, + "timestamp": 1591402521, + "timestampms": 1591402521272, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557835, + "timestamp": 1591402511, + "timestampms": 1591402511136, + "type": "sell" + }, + { + "amount": "0.00184", + "exchange": "gemini", + "price": "9578.40", + "tid": 607557829, + "timestamp": 1591402500, + "timestampms": 1591402500995, + "type": "buy" + }, + { + "amount": "0.00016", + "exchange": "gemini", + "price": "9573.15", + "tid": 607557827, + "timestamp": 1591402500, + "timestampms": 1591402500995, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557820, + "timestamp": 1591402490, + "timestampms": 1591402490847, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9570.57", + "tid": 607557814, + "timestamp": 1591402480, + "timestampms": 1591402480707, + "type": "sell" + }, + { + "amount": "0.00016", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557635, + "timestamp": 1591402472, + "timestampms": 1591402472482, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557570, + "timestamp": 1591402470, + "timestampms": 1591402470559, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557564, + "timestamp": 1591402460, + "timestampms": 1591402460385, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.16", + "tid": 607557557, + "timestamp": 1591402450, + "timestampms": 1591402450249, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557551, + "timestamp": 1591402440, + "timestampms": 1591402440111, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557544, + "timestamp": 1591402429, + "timestampms": 1591402429971, + "type": "buy" + }, + { + "amount": "0.001692", + "exchange": "gemini", + "price": "9573.81", + "tid": 607557538, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.000154", + "exchange": "gemini", + "price": "9573.76", + "tid": 607557536, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.000154", + "exchange": "gemini", + "price": "9573.76", + "tid": 607557534, + "timestamp": 1591402419, + "timestampms": 1591402419829, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607557295, + "timestamp": 1591402409, + "timestampms": 1591402409663, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9569.74", + "tid": 607557289, + "timestamp": 1591402399, + "timestampms": 1591402399492, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557282, + "timestamp": 1591402389, + "timestampms": 1591402389341, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557276, + "timestamp": 1591402379, + "timestampms": 1591402379192, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557269, + "timestamp": 1591402369, + "timestampms": 1591402369056, + "type": "buy" + }, + { + "amount": "0.001432", + "exchange": "gemini", + "price": "9574.29", + "tid": 607557263, + "timestamp": 1591402358, + "timestampms": 1591402358915, + "type": "buy" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9570.79", + "tid": 607557261, + "timestamp": 1591402358, + "timestampms": 1591402358915, + "type": "buy" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9574.60", + "tid": 607557082, + "timestamp": 1591402350, + "timestampms": 1591402350133, + "type": "sell" + }, + { + "amount": "0.199432", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557080, + "timestamp": 1591402350, + "timestampms": 1591402350133, + "type": "sell" + }, + { + "amount": "0.000568", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557075, + "timestamp": 1591402350, + "timestampms": 1591402350103, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557010, + "timestamp": 1591402348, + "timestampms": 1591402348773, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607557004, + "timestamp": 1591402338, + "timestampms": 1591402338629, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556997, + "timestamp": 1591402328, + "timestampms": 1591402328482, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556991, + "timestamp": 1591402318, + "timestampms": 1591402318335, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556983, + "timestamp": 1591402308, + "timestampms": 1591402308184, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.61", + "tid": 607556977, + "timestamp": 1591402298, + "timestampms": 1591402298050, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.61", + "tid": 607556730, + "timestamp": 1591402287, + "timestampms": 1591402287901, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.61", + "tid": 607556724, + "timestamp": 1591402277, + "timestampms": 1591402277767, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556717, + "timestamp": 1591402267, + "timestampms": 1591402267632, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556710, + "timestamp": 1591402257, + "timestampms": 1591402257488, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556704, + "timestamp": 1591402247, + "timestampms": 1591402247330, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.67", + "tid": 607556698, + "timestamp": 1591402237, + "timestampms": 1591402237187, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556450, + "timestamp": 1591402227, + "timestampms": 1591402227039, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556444, + "timestamp": 1591402216, + "timestampms": 1591402216896, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556437, + "timestamp": 1591402206, + "timestampms": 1591402206753, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556430, + "timestamp": 1591402196, + "timestampms": 1591402196549, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556423, + "timestamp": 1591402186, + "timestampms": 1591402186376, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9585.70", + "tid": 607556417, + "timestamp": 1591402176, + "timestampms": 1591402176219, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556176, + "timestamp": 1591402166, + "timestampms": 1591402166053, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556170, + "timestamp": 1591402155, + "timestampms": 1591402155900, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556162, + "timestamp": 1591402145, + "timestampms": 1591402145728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556156, + "timestamp": 1591402135, + "timestampms": 1591402135581, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556150, + "timestamp": 1591402125, + "timestampms": 1591402125396, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9581.29", + "tid": 607556143, + "timestamp": 1591402115, + "timestampms": 1591402115219, + "type": "buy" + }, + { + "amount": "0.364422", + "exchange": "gemini", + "price": "9582.65", + "tid": 607555989, + "timestamp": 1591402105, + "timestampms": 1591402105761, + "type": "sell" + }, + { + "amount": "0.100578", + "exchange": "gemini", + "price": "9582.65", + "tid": 607555984, + "timestamp": 1591402105, + "timestampms": 1591402105737, + "type": "sell" + }, + { + "amount": "0.193611", + "exchange": "gemini", + "price": "9584.35", + "tid": 607555982, + "timestamp": 1591402105, + "timestampms": 1591402105737, + "type": "sell" + }, + { + "amount": "0.306389", + "exchange": "gemini", + "price": "9584.35", + "tid": 607555977, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "1.9955", + "exchange": "gemini", + "price": "9585.04", + "tid": 607555975, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.128996", + "exchange": "gemini", + "price": "9586.83", + "tid": 607555973, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.114062", + "exchange": "gemini", + "price": "9586.84", + "tid": 607555971, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.108465", + "exchange": "gemini", + "price": "9587.00", + "tid": 607555969, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9587.29", + "tid": 607555967, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.9", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555965, + "timestamp": 1591402105, + "timestampms": 1591402105710, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555900, + "timestamp": 1591402105, + "timestampms": 1591402105034, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555893, + "timestamp": 1591402094, + "timestampms": 1591402094884, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555886, + "timestamp": 1591402084, + "timestampms": 1591402084745, + "type": "sell" + }, + { + "amount": "0.0005071", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555879, + "timestamp": 1591402074, + "timestampms": 1591402074593, + "type": "sell" + }, + { + "amount": "0.0006448", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555874, + "timestamp": 1591402074, + "timestampms": 1591402074564, + "type": "buy" + }, + { + "amount": "0.0004319", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555867, + "timestamp": 1591402064, + "timestampms": 1591402064383, + "type": "sell" + }, + { + "amount": "0.0008555", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555862, + "timestamp": 1591402064, + "timestampms": 1591402064357, + "type": "buy" + }, + { + "amount": "0.0004368", + "exchange": "gemini", + "price": "9587.70", + "tid": 607555856, + "timestamp": 1591402054, + "timestampms": 1591402054212, + "type": "sell" + }, + { + "amount": "0.0006728", + "exchange": "gemini", + "price": "9595.43", + "tid": 607555851, + "timestamp": 1591402054, + "timestampms": 1591402054186, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555652, + "timestamp": 1591402044, + "timestampms": 1591402044042, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555646, + "timestamp": 1591402033, + "timestampms": 1591402033899, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555639, + "timestamp": 1591402023, + "timestampms": 1591402023736, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555633, + "timestamp": 1591402013, + "timestampms": 1591402013590, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555627, + "timestamp": 1591402003, + "timestampms": 1591402003445, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9591.61", + "tid": 607555619, + "timestamp": 1591401993, + "timestampms": 1591401993297, + "type": "buy" + }, + { + "amount": "0.489786", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555458, + "timestamp": 1591401983, + "timestampms": 1591401983795, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555377, + "timestamp": 1591401983, + "timestampms": 1591401983154, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555341, + "timestamp": 1591401972, + "timestampms": 1591401972916, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555334, + "timestamp": 1591401962, + "timestampms": 1591401962775, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555327, + "timestamp": 1591401952, + "timestampms": 1591401952628, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555319, + "timestamp": 1591401942, + "timestampms": 1591401942466, + "type": "buy" + }, + { + "amount": "0.000214", + "exchange": "gemini", + "price": "9578.82", + "tid": 607555312, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.000893", + "exchange": "gemini", + "price": "9576.28", + "tid": 607555310, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.000893", + "exchange": "gemini", + "price": "9576.28", + "tid": 607555308, + "timestamp": 1591401932, + "timestampms": 1591401932300, + "type": "buy" + }, + { + "amount": "0.0000244", + "exchange": "gemini", + "price": "9571.65", + "tid": 607555146, + "timestamp": 1591401922, + "timestampms": 1591401922147, + "type": "sell" + }, + { + "amount": "0.0008145", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555138, + "timestamp": 1591401922, + "timestampms": 1591401922121, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555110, + "timestamp": 1591401911, + "timestampms": 1591401911975, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555103, + "timestamp": 1591401901, + "timestampms": 1591401901829, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555096, + "timestamp": 1591401891, + "timestampms": 1591401891684, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555090, + "timestamp": 1591401881, + "timestampms": 1591401881540, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9588.61", + "tid": 607555082, + "timestamp": 1591401871, + "timestampms": 1591401871392, + "type": "buy" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554960, + "timestamp": 1591401861, + "timestampms": 1591401861706, + "type": "buy" + }, + { + "amount": "0.603", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554955, + "timestamp": 1591401861, + "timestampms": 1591401861682, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554950, + "timestamp": 1591401861, + "timestampms": 1591401861656, + "type": "buy" + }, + { + "amount": "0.613", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554945, + "timestamp": 1591401861, + "timestampms": 1591401861632, + "type": "buy" + }, + { + "amount": "0.108436", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554937, + "timestamp": 1591401861, + "timestampms": 1591401861608, + "type": "buy" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554929, + "timestamp": 1591401861, + "timestampms": 1591401861582, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.21", + "tid": 607554885, + "timestamp": 1591401861, + "timestampms": 1591401861253, + "type": "buy" + }, + { + "amount": "0.253645", + "exchange": "gemini", + "price": "9572.78", + "tid": 607554828, + "timestamp": 1591401860, + "timestampms": 1591401860909, + "type": "buy" + }, + { + "amount": "0.246355", + "exchange": "gemini", + "price": "9572.78", + "tid": 607554823, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.32042", + "exchange": "gemini", + "price": "9572.77", + "tid": 607554821, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.046225", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554819, + "timestamp": 1591401860, + "timestampms": 1591401860883, + "type": "buy" + }, + { + "amount": "0.108436", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554814, + "timestamp": 1591401860, + "timestampms": 1591401860858, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554807, + "timestamp": 1591401851, + "timestampms": 1591401851121, + "type": "buy" + }, + { + "amount": "0.001409", + "exchange": "gemini", + "price": "9572.76", + "tid": 607554800, + "timestamp": 1591401840, + "timestampms": 1591401840976, + "type": "buy" + }, + { + "amount": "0.000591", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554798, + "timestamp": 1591401840, + "timestampms": 1591401840976, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554791, + "timestamp": 1591401830, + "timestampms": 1591401830835, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554785, + "timestamp": 1591401820, + "timestampms": 1591401820659, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9567.67", + "tid": 607554778, + "timestamp": 1591401810, + "timestampms": 1591401810515, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9573.82", + "tid": 607554615, + "timestamp": 1591401800, + "timestampms": 1591401800338, + "type": "sell" + }, + { + "amount": "0.99239", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554607, + "timestamp": 1591401800, + "timestampms": 1591401800302, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554602, + "timestamp": 1591401800, + "timestampms": 1591401800273, + "type": "sell" + }, + { + "amount": "0.32042", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554597, + "timestamp": 1591401800, + "timestampms": 1591401800247, + "type": "sell" + }, + { + "amount": "0.15807", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554592, + "timestamp": 1591401800, + "timestampms": 1591401800222, + "type": "sell" + }, + { + "amount": "0.00792", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554587, + "timestamp": 1591401800, + "timestampms": 1591401800198, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554520, + "timestamp": 1591401790, + "timestampms": 1591401790181, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554513, + "timestamp": 1591401780, + "timestampms": 1591401780049, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554507, + "timestamp": 1591401769, + "timestampms": 1591401769871, + "type": "sell" + }, + { + "amount": "0.000971", + "exchange": "gemini", + "price": "9577.43", + "tid": 607554501, + "timestamp": 1591401759, + "timestampms": 1591401759697, + "type": "buy" + }, + { + "amount": "0.001029", + "exchange": "gemini", + "price": "9577.43", + "tid": 607554499, + "timestamp": 1591401759, + "timestampms": 1591401759697, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.32", + "tid": 607554491, + "timestamp": 1591401749, + "timestampms": 1591401749525, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9574.73", + "tid": 607554389, + "timestamp": 1591401739, + "timestampms": 1591401739377, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554238, + "timestamp": 1591401729, + "timestampms": 1591401729237, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554232, + "timestamp": 1591401719, + "timestampms": 1591401719078, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554225, + "timestamp": 1591401708, + "timestampms": 1591401708928, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554218, + "timestamp": 1591401698, + "timestampms": 1591401698711, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554211, + "timestamp": 1591401688, + "timestampms": 1591401688541, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9578.96", + "tid": 607554145, + "timestamp": 1591401678, + "timestampms": 1591401678352, + "type": "buy" + }, + { + "amount": "0.016365", + "exchange": "gemini", + "price": "9602.93", + "tid": 607554062, + "timestamp": 1591401677, + "timestampms": 1591401677758, + "type": "sell" + }, + { + "amount": "0.8", + "exchange": "gemini", + "price": "9603.31", + "tid": 607554060, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9604.18", + "tid": 607554058, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9605.71", + "tid": 607554056, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.00052", + "exchange": "gemini", + "price": "9607.78", + "tid": 607554054, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.102932", + "exchange": "gemini", + "price": "9607.79", + "tid": 607554052, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "1.102967", + "exchange": "gemini", + "price": "9608.00", + "tid": 607554050, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.105302", + "exchange": "gemini", + "price": "9608.01", + "tid": 607554048, + "timestamp": 1591401677, + "timestampms": 1591401677757, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9608.01", + "tid": 607553987, + "timestamp": 1591401668, + "timestampms": 1591401668204, + "type": "sell" + }, + { + "amount": "0.000408", + "exchange": "gemini", + "price": "9608.01", + "tid": 607553980, + "timestamp": 1591401658, + "timestampms": 1591401658050, + "type": "sell" + }, + { + "amount": "0.001592", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553978, + "timestamp": 1591401658, + "timestampms": 1591401658050, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553972, + "timestamp": 1591401647, + "timestampms": 1591401647914, + "type": "sell" + }, + { + "amount": "0.001166", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553966, + "timestamp": 1591401637, + "timestampms": 1591401637768, + "type": "sell" + }, + { + "amount": "0.000834", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553964, + "timestamp": 1591401637, + "timestampms": 1591401637768, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553956, + "timestamp": 1591401627, + "timestampms": 1591401627618, + "type": "sell" + }, + { + "amount": "0.001924", + "exchange": "gemini", + "price": "9611.47", + "tid": 607553908, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.000038", + "exchange": "gemini", + "price": "9611.70", + "tid": 607553906, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.000038", + "exchange": "gemini", + "price": "9611.70", + "tid": 607553904, + "timestamp": 1591401617, + "timestampms": 1591401617471, + "type": "sell" + }, + { + "amount": "0.204253", + "exchange": "gemini", + "price": "9614.81", + "tid": 607553797, + "timestamp": 1591401616, + "timestampms": 1591401616739, + "type": "sell" + }, + { + "amount": "0.793747", + "exchange": "gemini", + "price": "9614.81", + "tid": 607553792, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.5", + "exchange": "gemini", + "price": "9616.60", + "tid": 607553790, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.553", + "exchange": "gemini", + "price": "9616.71", + "tid": 607553788, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.95", + "exchange": "gemini", + "price": "9617.20", + "tid": 607553786, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.489653", + "exchange": "gemini", + "price": "9617.71", + "tid": 607553784, + "timestamp": 1591401616, + "timestampms": 1591401616713, + "type": "sell" + }, + { + "amount": "0.457347", + "exchange": "gemini", + "price": "9617.71", + "tid": 607553779, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.103958", + "exchange": "gemini", + "price": "9619.31", + "tid": 607553777, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.01", + "exchange": "gemini", + "price": "9621.20", + "tid": 607553775, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.328695", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553773, + "timestamp": 1591401616, + "timestampms": 1591401616688, + "type": "sell" + }, + { + "amount": "0.000637", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553768, + "timestamp": 1591401616, + "timestampms": 1591401616665, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "9621.21", + "tid": 607553701, + "timestamp": 1591401607, + "timestampms": 1591401607318, + "type": "sell" + } + ], + "queryString": "limit_trades=500\u0026since=1591401607", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382614, + "timestamp": 1598850933, + "timestampms": 1598850933484, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382608, + "timestamp": 1598850923, + "timestampms": 1598850923336, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382599, + "timestamp": 1598850913, + "timestampms": 1598850913194, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382590, + "timestamp": 1598850903, + "timestampms": 1598850903045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382583, + "timestamp": 1598850892, + "timestampms": 1598850892900, + "type": "buy" + }, + { + "amount": "0.0004687", + "exchange": "gemini", + "price": "11673.73", + "tid": 642382356, + "timestamp": 1598850882, + "timestampms": 1598850882772, + "type": "sell" + }, + { + "amount": "0.0005692", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382348, + "timestamp": 1598850882, + "timestampms": 1598850882747, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382322, + "timestamp": 1598850872, + "timestampms": 1598850872576, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382316, + "timestamp": 1598850862, + "timestampms": 1598850862450, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382306, + "timestamp": 1598850852, + "timestampms": 1598850852315, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382298, + "timestamp": 1598850842, + "timestampms": 1598850842188, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382291, + "timestamp": 1598850832, + "timestampms": 1598850832057, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.63", + "tid": 642382097, + "timestamp": 1598850821, + "timestampms": 1598850821925, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382035, + "timestamp": 1598850811, + "timestampms": 1598850811791, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382029, + "timestamp": 1598850801, + "timestampms": 1598850801664, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382020, + "timestamp": 1598850791, + "timestampms": 1598850791539, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382011, + "timestamp": 1598850781, + "timestampms": 1598850781412, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382004, + "timestamp": 1598850771, + "timestampms": 1598850771281, + "type": "buy" + }, + { + "amount": "0.0004377", + "exchange": "gemini", + "price": "11673.63", + "tid": 642381841, + "timestamp": 1598850761, + "timestampms": 1598850761036, + "type": "sell" + }, + { + "amount": "0.0009182", + "exchange": "gemini", + "price": "11674.19", + "tid": 642381833, + "timestamp": 1598850761, + "timestampms": 1598850761008, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381749, + "timestamp": 1598850750, + "timestampms": 1598850750865, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381741, + "timestamp": 1598850740, + "timestampms": 1598850740720, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381733, + "timestamp": 1598850730, + "timestampms": 1598850730596, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381725, + "timestamp": 1598850720, + "timestampms": 1598850720462, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381716, + "timestamp": 1598850710, + "timestampms": 1598850710332, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381579, + "timestamp": 1598850700, + "timestampms": 1598850700060, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381458, + "timestamp": 1598850689, + "timestampms": 1598850689923, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381450, + "timestamp": 1598850679, + "timestampms": 1598850679682, + "type": "buy" + }, + { + "amount": "0.0009278", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381443, + "timestamp": 1598850669, + "timestampms": 1598850669549, + "type": "sell" + }, + { + "amount": "0.0003379", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381438, + "timestamp": 1598850669, + "timestampms": 1598850669521, + "type": "buy" + }, + { + "amount": "0.0007846", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381429, + "timestamp": 1598850659, + "timestampms": 1598850659378, + "type": "sell" + }, + { + "amount": "0.0008162", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381424, + "timestamp": 1598850659, + "timestampms": 1598850659352, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381415, + "timestamp": 1598850649, + "timestampms": 1598850649213, + "type": "buy" + }, + { + "amount": "0.0006557", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381289, + "timestamp": 1598850639, + "timestampms": 1598850639081, + "type": "sell" + }, + { + "amount": "0.0008514", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381281, + "timestamp": 1598850639, + "timestampms": 1598850639058, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381156, + "timestamp": 1598850628, + "timestampms": 1598850628922, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381148, + "timestamp": 1598850618, + "timestampms": 1598850618784, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381140, + "timestamp": 1598850608, + "timestampms": 1598850608650, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381132, + "timestamp": 1598850598, + "timestampms": 1598850598513, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381123, + "timestamp": 1598850588, + "timestampms": 1598850588220, + "type": "buy" + }, + { + "amount": "0.0004102", + "exchange": "gemini", + "price": "11672.46", + "tid": 642381009, + "timestamp": 1598850578, + "timestampms": 1598850578084, + "type": "sell" + }, + { + "amount": "0.0004516", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381004, + "timestamp": 1598850578, + "timestampms": 1598850578058, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380888, + "timestamp": 1598850567, + "timestampms": 1598850567923, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380880, + "timestamp": 1598850557, + "timestampms": 1598850557779, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380873, + "timestamp": 1598850547, + "timestampms": 1598850547648, + "type": "buy" + }, + { + "amount": "0.000556", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380864, + "timestamp": 1598850537, + "timestampms": 1598850537513, + "type": "buy" + }, + { + "amount": "0.001444", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380862, + "timestamp": 1598850537, + "timestampms": 1598850537513, + "type": "buy" + }, + { + "amount": "0.000278", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380853, + "timestamp": 1598850527, + "timestampms": 1598850527379, + "type": "buy" + }, + { + "amount": "0.001722", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380851, + "timestamp": 1598850527, + "timestampms": 1598850527379, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380719, + "timestamp": 1598850517, + "timestampms": 1598850517088, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380585, + "timestamp": 1598850506, + "timestampms": 1598850506955, + "type": "buy" + }, + { + "amount": "0.0008279", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380577, + "timestamp": 1598850496, + "timestampms": 1598850496810, + "type": "sell" + }, + { + "amount": "0.0001668", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380572, + "timestamp": 1598850496, + "timestampms": 1598850496786, + "type": "buy" + }, + { + "amount": "0.000103", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380564, + "timestamp": 1598850486, + "timestampms": 1598850486626, + "type": "sell" + }, + { + "amount": "0.000036", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380559, + "timestamp": 1598850486, + "timestampms": 1598850486602, + "type": "buy" + }, + { + "amount": "0.0003708", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380550, + "timestamp": 1598850476, + "timestampms": 1598850476470, + "type": "sell" + }, + { + "amount": "0.0002739", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380545, + "timestamp": 1598850476, + "timestampms": 1598850476447, + "type": "buy" + }, + { + "amount": "0.0005922", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380537, + "timestamp": 1598850466, + "timestampms": 1598850466303, + "type": "sell" + }, + { + "amount": "0.000113", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380532, + "timestamp": 1598850466, + "timestampms": 1598850466278, + "type": "buy" + }, + { + "amount": "0.0001031", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380406, + "timestamp": 1598850456, + "timestampms": 1598850456001, + "type": "sell" + }, + { + "amount": "0.0006239", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380401, + "timestamp": 1598850455, + "timestampms": 1598850455976, + "type": "buy" + }, + { + "amount": "0.0007953", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380275, + "timestamp": 1598850445, + "timestampms": 1598850445838, + "type": "sell" + }, + { + "amount": "0.0000845", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380270, + "timestamp": 1598850445, + "timestampms": 1598850445814, + "type": "buy" + }, + { + "amount": "0.0009655", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380261, + "timestamp": 1598850435, + "timestampms": 1598850435687, + "type": "sell" + }, + { + "amount": "0.000135", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380256, + "timestamp": 1598850435, + "timestampms": 1598850435662, + "type": "buy" + }, + { + "amount": "0.0007829", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380250, + "timestamp": 1598850425, + "timestampms": 1598850425537, + "type": "sell" + }, + { + "amount": "0.0007139", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380245, + "timestamp": 1598850425, + "timestampms": 1598850425513, + "type": "buy" + }, + { + "amount": "0.0001776", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380235, + "timestamp": 1598850415, + "timestampms": 1598850415374, + "type": "sell" + }, + { + "amount": "0.0001376", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380230, + "timestamp": 1598850415, + "timestampms": 1598850415350, + "type": "buy" + }, + { + "amount": "0.0001576", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380222, + "timestamp": 1598850405, + "timestampms": 1598850405224, + "type": "sell" + }, + { + "amount": "0.0005596", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380217, + "timestamp": 1598850405, + "timestampms": 1598850405200, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380091, + "timestamp": 1598850395, + "timestampms": 1598850395060, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379961, + "timestamp": 1598850384, + "timestampms": 1598850384924, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379951, + "timestamp": 1598850374, + "timestampms": 1598850374798, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379945, + "timestamp": 1598850364, + "timestampms": 1598850364666, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379936, + "timestamp": 1598850354, + "timestampms": 1598850354526, + "type": "buy" + }, + { + "amount": "0.0009645", + "exchange": "gemini", + "price": "11669.16", + "tid": 642379928, + "timestamp": 1598850344, + "timestampms": 1598850344403, + "type": "sell" + }, + { + "amount": "0.0001812", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379923, + "timestamp": 1598850344, + "timestampms": 1598850344379, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379812, + "timestamp": 1598850334, + "timestampms": 1598850334251, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379690, + "timestamp": 1598850324, + "timestampms": 1598850324122, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379681, + "timestamp": 1598850313, + "timestampms": 1598850313988, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379675, + "timestamp": 1598850303, + "timestampms": 1598850303858, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379665, + "timestamp": 1598850293, + "timestampms": 1598850293614, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379657, + "timestamp": 1598850283, + "timestampms": 1598850283474, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379539, + "timestamp": 1598850273, + "timestampms": 1598850273337, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379425, + "timestamp": 1598850263, + "timestampms": 1598850263198, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379415, + "timestamp": 1598850253, + "timestampms": 1598850253047, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379409, + "timestamp": 1598850242, + "timestampms": 1598850242886, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379400, + "timestamp": 1598850232, + "timestampms": 1598850232657, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379392, + "timestamp": 1598850222, + "timestampms": 1598850222532, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379263, + "timestamp": 1598850212, + "timestampms": 1598850212403, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379129, + "timestamp": 1598850202, + "timestampms": 1598850202277, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379120, + "timestamp": 1598850192, + "timestampms": 1598850192151, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379114, + "timestamp": 1598850181, + "timestampms": 1598850181998, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379104, + "timestamp": 1598850171, + "timestampms": 1598850171688, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379096, + "timestamp": 1598850161, + "timestampms": 1598850161554, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378964, + "timestamp": 1598850151, + "timestampms": 1598850151412, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378832, + "timestamp": 1598850141, + "timestampms": 1598850141273, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378822, + "timestamp": 1598850131, + "timestampms": 1598850131118, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378816, + "timestamp": 1598850120, + "timestampms": 1598850120980, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378807, + "timestamp": 1598850110, + "timestampms": 1598850110733, + "type": "buy" + }, + { + "amount": "0.0007051", + "exchange": "gemini", + "price": "11660.00", + "tid": 642378799, + "timestamp": 1598850100, + "timestampms": 1598850100603, + "type": "sell" + }, + { + "amount": "0.0001487", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378794, + "timestamp": 1598850100, + "timestampms": 1598850100578, + "type": "buy" + }, + { + "amount": "0.0004598", + "exchange": "gemini", + "price": "11660.00", + "tid": 642378674, + "timestamp": 1598850090, + "timestampms": 1598850090454, + "type": "sell" + }, + { + "amount": "0.0001629", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378669, + "timestamp": 1598850090, + "timestampms": 1598850090428, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11662.19", + "tid": 642378610, + "timestamp": 1598850088, + "timestampms": 1598850088243, + "type": "sell" + }, + { + "amount": "0.192", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378608, + "timestamp": 1598850088, + "timestampms": 1598850088243, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378540, + "timestamp": 1598850080, + "timestampms": 1598850080304, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378531, + "timestamp": 1598850070, + "timestampms": 1598850070158, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378523, + "timestamp": 1598850060, + "timestampms": 1598850060026, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378515, + "timestamp": 1598850049, + "timestampms": 1598850049781, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11665.35", + "tid": 642378507, + "timestamp": 1598850039, + "timestampms": 1598850039647, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.48", + "tid": 642378384, + "timestamp": 1598850029, + "timestampms": 1598850029519, + "type": "sell" + }, + { + "amount": "0.135589", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378323, + "timestamp": 1598850026, + "timestampms": 1598850026998, + "type": "sell" + }, + { + "amount": "0.059484", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378318, + "timestamp": 1598850026, + "timestampms": 1598850026974, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11667.83", + "tid": 642378255, + "timestamp": 1598850019, + "timestampms": 1598850019381, + "type": "buy" + }, + { + "amount": "0.001923", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378245, + "timestamp": 1598850009, + "timestampms": 1598850009249, + "type": "sell" + }, + { + "amount": "0.000077", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378243, + "timestamp": 1598850009, + "timestampms": 1598850009249, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378236, + "timestamp": 1598849999, + "timestampms": 1598849999112, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378228, + "timestamp": 1598849988, + "timestampms": 1598849988977, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378220, + "timestamp": 1598849978, + "timestampms": 1598849978847, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378094, + "timestamp": 1598849968, + "timestampms": 1598849968712, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377966, + "timestamp": 1598849958, + "timestampms": 1598849958583, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377957, + "timestamp": 1598849948, + "timestampms": 1598849948443, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377949, + "timestamp": 1598849938, + "timestampms": 1598849938314, + "type": "buy" + }, + { + "amount": "0.0001767", + "exchange": "gemini", + "price": "11666.38", + "tid": 642377941, + "timestamp": 1598849928, + "timestampms": 1598849928173, + "type": "sell" + }, + { + "amount": "0.0006903", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377936, + "timestamp": 1598849928, + "timestampms": 1598849928148, + "type": "buy" + }, + { + "amount": "0.0004407", + "exchange": "gemini", + "price": "11666.38", + "tid": 642377928, + "timestamp": 1598849918, + "timestampms": 1598849918019, + "type": "sell" + }, + { + "amount": "0.0005044", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377923, + "timestamp": 1598849917, + "timestampms": 1598849917988, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11670.29", + "tid": 642377800, + "timestamp": 1598849907, + "timestampms": 1598849907844, + "type": "buy" + }, + { + "amount": "0.0043675", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377735, + "timestamp": 1598849904, + "timestampms": 1598849904696, + "type": "sell" + }, + { + "amount": "0.0006755", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377673, + "timestamp": 1598849897, + "timestampms": 1598849897712, + "type": "sell" + }, + { + "amount": "0.0013245", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377671, + "timestamp": 1598849897, + "timestampms": 1598849897712, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377661, + "timestamp": 1598849887, + "timestampms": 1598849887583, + "type": "sell" + }, + { + "amount": "0.0006439", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377654, + "timestamp": 1598849877, + "timestampms": 1598849877447, + "type": "sell" + }, + { + "amount": "0.0007116", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377649, + "timestamp": 1598849877, + "timestampms": 1598849877424, + "type": "buy" + }, + { + "amount": "0.0004047", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377641, + "timestamp": 1598849867, + "timestampms": 1598849867275, + "type": "sell" + }, + { + "amount": "0.0001902", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377636, + "timestamp": 1598849867, + "timestampms": 1598849867248, + "type": "buy" + }, + { + "amount": "0.0005595", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377628, + "timestamp": 1598849857, + "timestampms": 1598849857116, + "type": "sell" + }, + { + "amount": "0.000024", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377623, + "timestamp": 1598849857, + "timestampms": 1598849857090, + "type": "buy" + }, + { + "amount": "0.0001104", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377506, + "timestamp": 1598849846, + "timestampms": 1598849846967, + "type": "sell" + }, + { + "amount": "0.0006308", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377501, + "timestamp": 1598849846, + "timestampms": 1598849846941, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11670.97", + "tid": 642377436, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.015212", + "exchange": "gemini", + "price": "11671.14", + "tid": 642377434, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.035291", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377432, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377367, + "timestamp": 1598849836, + "timestampms": 1598849836806, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377358, + "timestamp": 1598849826, + "timestampms": 1598849826685, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377350, + "timestamp": 1598849816, + "timestampms": 1598849816553, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377342, + "timestamp": 1598849806, + "timestampms": 1598849806400, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377334, + "timestamp": 1598849796, + "timestampms": 1598849796250, + "type": "sell" + }, + { + "amount": "0.0001237", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377212, + "timestamp": 1598849786, + "timestampms": 1598849786115, + "type": "sell" + }, + { + "amount": "0.0006136", + "exchange": "gemini", + "price": "11675.05", + "tid": 642377204, + "timestamp": 1598849786, + "timestampms": 1598849786091, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377073, + "timestamp": 1598849775, + "timestampms": 1598849775948, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377062, + "timestamp": 1598849765, + "timestampms": 1598849765809, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377055, + "timestamp": 1598849755, + "timestampms": 1598849755671, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377047, + "timestamp": 1598849745, + "timestampms": 1598849745515, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377039, + "timestamp": 1598849735, + "timestampms": 1598849735386, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.93", + "tid": 642376938, + "timestamp": 1598849725, + "timestampms": 1598849725263, + "type": "buy" + }, + { + "amount": "0.1", + "exchange": "gemini", + "price": "11671.31", + "tid": 642376780, + "timestamp": 1598849716, + "timestampms": 1598849716657, + "type": "sell" + }, + { + "amount": "0.057156", + "exchange": "gemini", + "price": "11673.93", + "tid": 642376775, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.026422", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376773, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.016422", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376771, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376764, + "timestamp": 1598849715, + "timestampms": 1598849715126, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376756, + "timestamp": 1598849704, + "timestampms": 1598849704972, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376748, + "timestamp": 1598849694, + "timestampms": 1598849694844, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376740, + "timestamp": 1598849684, + "timestampms": 1598849684709, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376732, + "timestamp": 1598849674, + "timestampms": 1598849674523, + "type": "buy" + }, + { + "amount": "0.000881", + "exchange": "gemini", + "price": "11671.31", + "tid": 642376663, + "timestamp": 1598849664, + "timestampms": 1598849664401, + "type": "sell" + }, + { + "amount": "0.000555", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376655, + "timestamp": 1598849664, + "timestampms": 1598849664377, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376471, + "timestamp": 1598849654, + "timestampms": 1598849654238, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376463, + "timestamp": 1598849644, + "timestampms": 1598849644105, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376456, + "timestamp": 1598849633, + "timestampms": 1598849633982, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376448, + "timestamp": 1598849623, + "timestampms": 1598849623810, + "type": "buy" + }, + { + "amount": "0.0009903", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376440, + "timestamp": 1598849613, + "timestampms": 1598849613676, + "type": "sell" + }, + { + "amount": "0.0005454", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376435, + "timestamp": 1598849613, + "timestampms": 1598849613651, + "type": "buy" + }, + { + "amount": "0.0008607", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376390, + "timestamp": 1598849603, + "timestampms": 1598849603501, + "type": "sell" + }, + { + "amount": "0.0001283", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376382, + "timestamp": 1598849603, + "timestampms": 1598849603477, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376181, + "timestamp": 1598849593, + "timestampms": 1598849593341, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376172, + "timestamp": 1598849583, + "timestampms": 1598849583216, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376165, + "timestamp": 1598849573, + "timestampms": 1598849573077, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376157, + "timestamp": 1598849562, + "timestampms": 1598849562928, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376149, + "timestamp": 1598849552, + "timestampms": 1598849552785, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376134, + "timestamp": 1598849542, + "timestampms": 1598849542654, + "type": "buy" + }, + { + "amount": "0.1569041", + "exchange": "gemini", + "price": "11669.39", + "tid": 642375912, + "timestamp": 1598849537, + "timestampms": 1598849537285, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11669.19", + "tid": 642375910, + "timestamp": 1598849537, + "timestampms": 1598849537284, + "type": "buy" + }, + { + "amount": "0.0430959", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375908, + "timestamp": 1598849537, + "timestampms": 1598849537284, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375900, + "timestamp": 1598849532, + "timestampms": 1598849532516, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375892, + "timestamp": 1598849522, + "timestampms": 1598849522392, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375885, + "timestamp": 1598849512, + "timestampms": 1598849512249, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375877, + "timestamp": 1598849502, + "timestampms": 1598849502084, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375869, + "timestamp": 1598849491, + "timestampms": 1598849491951, + "type": "buy" + }, + { + "amount": "0.0009811", + "exchange": "gemini", + "price": "11667.07", + "tid": 642375863, + "timestamp": 1598849481, + "timestampms": 1598849481820, + "type": "sell" + }, + { + "amount": "0.0005331", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375858, + "timestamp": 1598849481, + "timestampms": 1598849481796, + "type": "buy" + }, + { + "amount": "0.0019642", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375692, + "timestamp": 1598849476, + "timestampms": 1598849476759, + "type": "sell" + }, + { + "amount": "1.0834", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375687, + "timestamp": 1598849476, + "timestampms": 1598849476736, + "type": "sell" + }, + { + "amount": "0.9146358", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375682, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.95", + "exchange": "gemini", + "price": "11672.60", + "tid": 642375680, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.1353642", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375678, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.055566", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375673, + "timestamp": 1598849476, + "timestampms": 1598849476686, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375606, + "timestamp": 1598849471, + "timestampms": 1598849471659, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375597, + "timestamp": 1598849461, + "timestampms": 1598849461522, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375590, + "timestamp": 1598849451, + "timestampms": 1598849451386, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375582, + "timestamp": 1598849441, + "timestampms": 1598849441233, + "type": "sell" + }, + { + "amount": "0.0003074", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375574, + "timestamp": 1598849431, + "timestampms": 1598849431089, + "type": "sell" + }, + { + "amount": "0.0000432", + "exchange": "gemini", + "price": "11674.88", + "tid": 642375569, + "timestamp": 1598849431, + "timestampms": 1598849431065, + "type": "buy" + }, + { + "amount": "0.0007624", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375563, + "timestamp": 1598849420, + "timestampms": 1598849420933, + "type": "sell" + }, + { + "amount": "0.0009046", + "exchange": "gemini", + "price": "11674.88", + "tid": 642375558, + "timestamp": 1598849420, + "timestampms": 1598849420908, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375323, + "timestamp": 1598849410, + "timestampms": 1598849410765, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375315, + "timestamp": 1598849400, + "timestampms": 1598849400634, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375306, + "timestamp": 1598849390, + "timestampms": 1598849390359, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375300, + "timestamp": 1598849380, + "timestampms": 1598849380229, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375292, + "timestamp": 1598849370, + "timestampms": 1598849370097, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375284, + "timestamp": 1598849359, + "timestampms": 1598849359868, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11668.96", + "tid": 642375075, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11668.92", + "tid": 642375073, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "0.148428", + "exchange": "gemini", + "price": "11668.38", + "tid": 642375071, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "0.10492", + "exchange": "gemini", + "price": "11667.05", + "tid": 642375069, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "1.425161", + "exchange": "gemini", + "price": "11667.05", + "tid": 642375064, + "timestamp": 1598849353, + "timestampms": 1598849353957, + "type": "buy" + }, + { + "amount": "0.574839", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375062, + "timestamp": 1598849353, + "timestampms": 1598849353957, + "type": "buy" + }, + { + "amount": "0.1677", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375057, + "timestamp": 1598849353, + "timestampms": 1598849353932, + "type": "buy" + }, + { + "amount": "0.146959", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375052, + "timestamp": 1598849353, + "timestampms": 1598849353907, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375047, + "timestamp": 1598849349, + "timestampms": 1598849349726, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375038, + "timestamp": 1598849339, + "timestampms": 1598849339574, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375029, + "timestamp": 1598849329, + "timestampms": 1598849329315, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375023, + "timestamp": 1598849319, + "timestampms": 1598849319190, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375015, + "timestamp": 1598849309, + "timestampms": 1598849309062, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375007, + "timestamp": 1598849298, + "timestampms": 1598849298815, + "type": "buy" + }, + { + "amount": "0.488", + "exchange": "gemini", + "price": "11669.76", + "tid": 642374864, + "timestamp": 1598849293, + "timestampms": 1598849293430, + "type": "sell" + }, + { + "amount": "2.543086", + "exchange": "gemini", + "price": "11671.50", + "tid": 642374862, + "timestamp": 1598849293, + "timestampms": 1598849293430, + "type": "sell" + }, + { + "amount": "1.356914", + "exchange": "gemini", + "price": "11671.50", + "tid": 642374857, + "timestamp": 1598849293, + "timestampms": 1598849293406, + "type": "sell" + }, + { + "amount": "0.643086", + "exchange": "gemini", + "price": "11672.00", + "tid": 642374855, + "timestamp": 1598849293, + "timestampms": 1598849293406, + "type": "sell" + }, + { + "amount": "0.353914", + "exchange": "gemini", + "price": "11672.00", + "tid": 642374850, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "1.9491", + "exchange": "gemini", + "price": "11672.90", + "tid": 642374848, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.007", + "exchange": "gemini", + "price": "11675.00", + "tid": 642374846, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11675.60", + "tid": 642374844, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.105886", + "exchange": "gemini", + "price": "11675.61", + "tid": 642374842, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.08543", + "exchange": "gemini", + "price": "11676.36", + "tid": 642374840, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.194168", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374838, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "1.446095", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374833, + "timestamp": 1598849293, + "timestampms": 1598849293359, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374828, + "timestamp": 1598849293, + "timestampms": 1598849293335, + "type": "sell" + }, + { + "amount": "0.149737", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374823, + "timestamp": 1598849293, + "timestampms": 1598849293312, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374758, + "timestamp": 1598849288, + "timestampms": 1598849288687, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11677.30", + "tid": 642374750, + "timestamp": 1598849278, + "timestampms": 1598849278530, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374741, + "timestamp": 1598849268, + "timestampms": 1598849268391, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374735, + "timestamp": 1598849258, + "timestampms": 1598849258259, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374727, + "timestamp": 1598849248, + "timestampms": 1598849248119, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374719, + "timestamp": 1598849237, + "timestampms": 1598849237959, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374475, + "timestamp": 1598849227, + "timestampms": 1598849227825, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374466, + "timestamp": 1598849217, + "timestampms": 1598849217692, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374457, + "timestamp": 1598849207, + "timestampms": 1598849207563, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374451, + "timestamp": 1598849197, + "timestampms": 1598849197432, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374443, + "timestamp": 1598849187, + "timestampms": 1598849187309, + "type": "buy" + }, + { + "amount": "0.0005913", + "exchange": "gemini", + "price": "11676.36", + "tid": 642374435, + "timestamp": 1598849177, + "timestampms": 1598849177023, + "type": "sell" + }, + { + "amount": "0.0009976", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374430, + "timestamp": 1598849177, + "timestampms": 1598849177000, + "type": "buy" + }, + { + "amount": "0.9914", + "exchange": "gemini", + "price": "11676.98", + "tid": 642374257, + "timestamp": 1598849171, + "timestampms": 1598849171204, + "type": "sell" + }, + { + "amount": "0.191467", + "exchange": "gemini", + "price": "11679.45", + "tid": 642374255, + "timestamp": 1598849171, + "timestampms": 1598849171203, + "type": "sell" + }, + { + "amount": "0.008533", + "exchange": "gemini", + "price": "11679.45", + "tid": 642374250, + "timestamp": 1598849171, + "timestampms": 1598849171179, + "type": "sell" + }, + { + "amount": "0.07914", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374248, + "timestamp": 1598849171, + "timestampms": 1598849171179, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374183, + "timestamp": 1598849166, + "timestampms": 1598849166869, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374175, + "timestamp": 1598849156, + "timestampms": 1598849156745, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374166, + "timestamp": 1598849146, + "timestampms": 1598849146605, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374160, + "timestamp": 1598849136, + "timestampms": 1598849136468, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374152, + "timestamp": 1598849126, + "timestampms": 1598849126338, + "type": "sell" + }, + { + "amount": "0.000177", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374144, + "timestamp": 1598849116, + "timestampms": 1598849116176, + "type": "sell" + }, + { + "amount": "0.0001439", + "exchange": "gemini", + "price": "11683.70", + "tid": 642374139, + "timestamp": 1598849116, + "timestampms": 1598849116152, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11681.43", + "tid": 642373903, + "timestamp": 1598849105, + "timestampms": 1598849105909, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373893, + "timestamp": 1598849095, + "timestampms": 1598849095774, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373885, + "timestamp": 1598849085, + "timestampms": 1598849085636, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373879, + "timestamp": 1598849075, + "timestampms": 1598849075500, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373871, + "timestamp": 1598849065, + "timestampms": 1598849065368, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373861, + "timestamp": 1598849055, + "timestampms": 1598849055223, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373607, + "timestamp": 1598849045, + "timestampms": 1598849045076, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373598, + "timestamp": 1598849034, + "timestampms": 1598849034933, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373590, + "timestamp": 1598849024, + "timestampms": 1598849024788, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373584, + "timestamp": 1598849014, + "timestampms": 1598849014665, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373576, + "timestamp": 1598849004, + "timestampms": 1598849004540, + "type": "buy" + }, + { + "amount": "0.0002445", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373567, + "timestamp": 1598848994, + "timestampms": 1598848994411, + "type": "sell" + }, + { + "amount": "0.000227", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373562, + "timestamp": 1598848994, + "timestampms": 1598848994386, + "type": "buy" + }, + { + "amount": "0.0003115", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373316, + "timestamp": 1598848984, + "timestampms": 1598848984137, + "type": "sell" + }, + { + "amount": "0.0005039", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373311, + "timestamp": 1598848984, + "timestampms": 1598848984114, + "type": "buy" + }, + { + "amount": "0.0001642", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373301, + "timestamp": 1598848973, + "timestampms": 1598848973980, + "type": "sell" + }, + { + "amount": "0.0008888", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373296, + "timestamp": 1598848973, + "timestampms": 1598848973951, + "type": "buy" + }, + { + "amount": "0.0003519", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373288, + "timestamp": 1598848963, + "timestampms": 1598848963819, + "type": "sell" + }, + { + "amount": "0.0000126", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373283, + "timestamp": 1598848963, + "timestampms": 1598848963795, + "type": "buy" + }, + { + "amount": "0.0001933", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373277, + "timestamp": 1598848953, + "timestampms": 1598848953668, + "type": "sell" + }, + { + "amount": "0.0002974", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373272, + "timestamp": 1598848953, + "timestampms": 1598848953643, + "type": "buy" + }, + { + "amount": "0.0001316", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373264, + "timestamp": 1598848943, + "timestampms": 1598848943512, + "type": "sell" + }, + { + "amount": "0.0006548", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373259, + "timestamp": 1598848943, + "timestampms": 1598848943487, + "type": "buy" + }, + { + "amount": "0.0003662", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373249, + "timestamp": 1598848933, + "timestampms": 1598848933357, + "type": "sell" + }, + { + "amount": "0.0006337", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373244, + "timestamp": 1598848933, + "timestampms": 1598848933331, + "type": "buy" + }, + { + "amount": "0.000218", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373010, + "timestamp": 1598848923, + "timestampms": 1598848923117, + "type": "buy" + }, + { + "amount": "0.001782", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373008, + "timestamp": 1598848923, + "timestampms": 1598848923117, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372999, + "timestamp": 1598848912, + "timestampms": 1598848912994, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372991, + "timestamp": 1598848902, + "timestampms": 1598848902857, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372985, + "timestamp": 1598848892, + "timestampms": 1598848892719, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372977, + "timestamp": 1598848882, + "timestampms": 1598848882595, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372968, + "timestamp": 1598848872, + "timestampms": 1598848872466, + "type": "buy" + }, + { + "amount": "1.681266", + "exchange": "gemini", + "price": "11681.92", + "tid": 642372842, + "timestamp": 1598848870, + "timestampms": 1598848870038, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372722, + "timestamp": 1598848862, + "timestampms": 1598848862334, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372712, + "timestamp": 1598848852, + "timestampms": 1598848852187, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372704, + "timestamp": 1598848842, + "timestampms": 1598848842032, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372698, + "timestamp": 1598848831, + "timestampms": 1598848831897, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372690, + "timestamp": 1598848821, + "timestampms": 1598848821764, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372680, + "timestamp": 1598848811, + "timestampms": 1598848811624, + "type": "buy" + }, + { + "amount": "0.290189", + "exchange": "gemini", + "price": "11684.30", + "tid": 642372515, + "timestamp": 1598848804, + "timestampms": 1598848804719, + "type": "sell" + }, + { + "amount": "0.659811", + "exchange": "gemini", + "price": "11684.30", + "tid": 642372510, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "1.268271", + "exchange": "gemini", + "price": "11685.15", + "tid": 642372508, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "0.071918", + "exchange": "gemini", + "price": "11687.57", + "tid": 642372506, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "0.128082", + "exchange": "gemini", + "price": "11687.57", + "tid": 642372501, + "timestamp": 1598848804, + "timestampms": 1598848804669, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11687.93", + "tid": 642372436, + "timestamp": 1598848801, + "timestampms": 1598848801493, + "type": "sell" + }, + { + "amount": "0.00039", + "exchange": "gemini", + "price": "11687.93", + "tid": 642372427, + "timestamp": 1598848791, + "timestampms": 1598848791212, + "type": "sell" + }, + { + "amount": "0.00161", + "exchange": "gemini", + "price": "11688.15", + "tid": 642372425, + "timestamp": 1598848791, + "timestampms": 1598848791212, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11688.15", + "tid": 642372417, + "timestamp": 1598848781, + "timestampms": 1598848781060, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372411, + "timestamp": 1598848770, + "timestampms": 1598848770927, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372403, + "timestamp": 1598848760, + "timestampms": 1598848760780, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372394, + "timestamp": 1598848750, + "timestampms": 1598848750644, + "type": "buy" + }, + { + "amount": "0.028876", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372213, + "timestamp": 1598848743, + "timestampms": 1598848743590, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372148, + "timestamp": 1598848740, + "timestampms": 1598848740496, + "type": "sell" + }, + { + "amount": "0.0004446", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372139, + "timestamp": 1598848730, + "timestampms": 1598848730225, + "type": "sell" + }, + { + "amount": "0.000044", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372134, + "timestamp": 1598848730, + "timestampms": 1598848730200, + "type": "buy" + }, + { + "amount": "0.0001986", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372126, + "timestamp": 1598848720, + "timestampms": 1598848720079, + "type": "sell" + }, + { + "amount": "0.0008563", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372121, + "timestamp": 1598848720, + "timestampms": 1598848720055, + "type": "buy" + }, + { + "amount": "0.0009112", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372115, + "timestamp": 1598848709, + "timestampms": 1598848709919, + "type": "sell" + }, + { + "amount": "0.000712", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372110, + "timestamp": 1598848709, + "timestampms": 1598848709894, + "type": "buy" + }, + { + "amount": "0.000613", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372102, + "timestamp": 1598848699, + "timestampms": 1598848699769, + "type": "sell" + }, + { + "amount": "0.0000581", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372097, + "timestamp": 1598848699, + "timestampms": 1598848699745, + "type": "buy" + }, + { + "amount": "0.0008616", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372087, + "timestamp": 1598848689, + "timestampms": 1598848689619, + "type": "sell" + }, + { + "amount": "0.0000267", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372082, + "timestamp": 1598848689, + "timestampms": 1598848689591, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371835, + "timestamp": 1598848679, + "timestampms": 1598848679459, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371827, + "timestamp": 1598848669, + "timestampms": 1598848669330, + "type": "buy" + }, + { + "amount": "0.0001012", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371819, + "timestamp": 1598848659, + "timestampms": 1598848659201, + "type": "sell" + }, + { + "amount": "0.0000288", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371814, + "timestamp": 1598848659, + "timestampms": 1598848659177, + "type": "buy" + }, + { + "amount": "0.0002001", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371808, + "timestamp": 1598848649, + "timestampms": 1598848649038, + "type": "sell" + }, + { + "amount": "0.000275", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371803, + "timestamp": 1598848649, + "timestampms": 1598848649013, + "type": "buy" + }, + { + "amount": "0.0001743", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371795, + "timestamp": 1598848638, + "timestampms": 1598848638865, + "type": "sell" + }, + { + "amount": "0.0009966", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371790, + "timestamp": 1598848638, + "timestampms": 1598848638839, + "type": "buy" + }, + { + "amount": "0.0007403", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371781, + "timestamp": 1598848628, + "timestampms": 1598848628676, + "type": "sell" + }, + { + "amount": "0.0001988", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371776, + "timestamp": 1598848628, + "timestampms": 1598848628651, + "type": "buy" + }, + { + "amount": "0.0005233", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371537, + "timestamp": 1598848618, + "timestampms": 1598848618506, + "type": "sell" + }, + { + "amount": "0.0004101", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371532, + "timestamp": 1598848618, + "timestampms": 1598848618481, + "type": "buy" + }, + { + "amount": "0.000092", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371524, + "timestamp": 1598848608, + "timestampms": 1598848608332, + "type": "sell" + }, + { + "amount": "0.0006655", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371519, + "timestamp": 1598848608, + "timestampms": 1598848608302, + "type": "buy" + }, + { + "amount": "0.0009364", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371511, + "timestamp": 1598848598, + "timestampms": 1598848598172, + "type": "sell" + }, + { + "amount": "0.0009631", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371506, + "timestamp": 1598848598, + "timestampms": 1598848598147, + "type": "buy" + }, + { + "amount": "0.0007104", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371500, + "timestamp": 1598848588, + "timestampms": 1598848588004, + "type": "sell" + }, + { + "amount": "0.000362", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371495, + "timestamp": 1598848587, + "timestampms": 1598848587980, + "type": "buy" + }, + { + "amount": "0.0001778", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371487, + "timestamp": 1598848577, + "timestampms": 1598848577840, + "type": "sell" + }, + { + "amount": "0.0005828", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371482, + "timestamp": 1598848577, + "timestampms": 1598848577817, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371472, + "timestamp": 1598848567, + "timestampms": 1598848567688, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371219, + "timestamp": 1598848557, + "timestampms": 1598848557549, + "type": "buy" + }, + { + "amount": "0.0006708", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371211, + "timestamp": 1598848547, + "timestampms": 1598848547421, + "type": "sell" + }, + { + "amount": "0.0007916", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371206, + "timestamp": 1598848547, + "timestampms": 1598848547398, + "type": "buy" + }, + { + "amount": "0.0007569", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371198, + "timestamp": 1598848537, + "timestampms": 1598848537260, + "type": "sell" + }, + { + "amount": "0.0007132", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371193, + "timestamp": 1598848537, + "timestampms": 1598848537231, + "type": "buy" + }, + { + "amount": "0.0008695", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371187, + "timestamp": 1598848526, + "timestampms": 1598848526955, + "type": "sell" + }, + { + "amount": "0.0002564", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371182, + "timestamp": 1598848526, + "timestampms": 1598848526931, + "type": "buy" + }, + { + "amount": "0.0002534", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371174, + "timestamp": 1598848516, + "timestampms": 1598848516799, + "type": "sell" + }, + { + "amount": "0.000248", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371169, + "timestamp": 1598848516, + "timestampms": 1598848516774, + "type": "buy" + }, + { + "amount": "0.0003681", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371160, + "timestamp": 1598848506, + "timestampms": 1598848506643, + "type": "sell" + }, + { + "amount": "0.000559", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371155, + "timestamp": 1598848506, + "timestampms": 1598848506619, + "type": "buy" + }, + { + "amount": "0.000298", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370910, + "timestamp": 1598848496, + "timestampms": 1598848496485, + "type": "sell" + }, + { + "amount": "0.0006147", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370905, + "timestamp": 1598848496, + "timestampms": 1598848496461, + "type": "buy" + }, + { + "amount": "0.0003912", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370897, + "timestamp": 1598848486, + "timestampms": 1598848486332, + "type": "sell" + }, + { + "amount": "0.0003537", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370892, + "timestamp": 1598848486, + "timestampms": 1598848486308, + "type": "buy" + }, + { + "amount": "0.0005441", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370884, + "timestamp": 1598848476, + "timestampms": 1598848476176, + "type": "sell" + }, + { + "amount": "0.0007024", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370879, + "timestamp": 1598848476, + "timestampms": 1598848476151, + "type": "buy" + }, + { + "amount": "0.0002039", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370873, + "timestamp": 1598848466, + "timestampms": 1598848466023, + "type": "sell" + }, + { + "amount": "0.0003968", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370871, + "timestamp": 1598848466, + "timestampms": 1598848466023, + "type": "sell" + }, + { + "amount": "0.0006368", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370866, + "timestamp": 1598848465, + "timestampms": 1598848465999, + "type": "buy" + }, + { + "amount": "0.0002646", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370855, + "timestamp": 1598848455, + "timestampms": 1598848455869, + "type": "sell" + }, + { + "amount": "0.000987", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370850, + "timestamp": 1598848455, + "timestampms": 1598848455844, + "type": "buy" + }, + { + "amount": "0.0009196", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370842, + "timestamp": 1598848445, + "timestampms": 1598848445701, + "type": "sell" + }, + { + "amount": "0.0004949", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370837, + "timestamp": 1598848445, + "timestampms": 1598848445675, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370600, + "timestamp": 1598848437, + "timestampms": 1598848437669, + "type": "buy" + }, + { + "amount": "0.069772", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370598, + "timestamp": 1598848437, + "timestampms": 1598848437669, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370592, + "timestamp": 1598848435, + "timestampms": 1598848435544, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370584, + "timestamp": 1598848425, + "timestampms": 1598848425409, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370576, + "timestamp": 1598848415, + "timestampms": 1598848415273, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370570, + "timestamp": 1598848405, + "timestampms": 1598848405137, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642370561, + "timestamp": 1598848395, + "timestampms": 1598848395009, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642370553, + "timestamp": 1598848384, + "timestampms": 1598848384746, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370305, + "timestamp": 1598848374, + "timestampms": 1598848374611, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370297, + "timestamp": 1598848364, + "timestampms": 1598848364470, + "type": "sell" + }, + { + "amount": "0.0006655", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370289, + "timestamp": 1598848354, + "timestampms": 1598848354343, + "type": "sell" + }, + { + "amount": "0.0007794", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370284, + "timestamp": 1598848354, + "timestampms": 1598848354320, + "type": "buy" + }, + { + "amount": "0.0005903", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370278, + "timestamp": 1598848344, + "timestampms": 1598848344188, + "type": "sell" + }, + { + "amount": "0.0001157", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370273, + "timestamp": 1598848344, + "timestampms": 1598848344158, + "type": "buy" + }, + { + "amount": "0.0003591", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370263, + "timestamp": 1598848334, + "timestampms": 1598848334025, + "type": "sell" + }, + { + "amount": "0.0004916", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370258, + "timestamp": 1598848333, + "timestampms": 1598848333991, + "type": "buy" + }, + { + "amount": "0.0006661", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370250, + "timestamp": 1598848323, + "timestampms": 1598848323857, + "type": "sell" + }, + { + "amount": "0.0004414", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370245, + "timestamp": 1598848323, + "timestampms": 1598848323831, + "type": "buy" + }, + { + "amount": "0.0006503", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369998, + "timestamp": 1598848313, + "timestampms": 1598848313694, + "type": "sell" + }, + { + "amount": "0.0004874", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369993, + "timestamp": 1598848313, + "timestampms": 1598848313670, + "type": "buy" + }, + { + "amount": "0.0002995", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369985, + "timestamp": 1598848303, + "timestampms": 1598848303537, + "type": "sell" + }, + { + "amount": "0.0005772", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369980, + "timestamp": 1598848303, + "timestampms": 1598848303514, + "type": "buy" + }, + { + "amount": "0.0009411", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369972, + "timestamp": 1598848293, + "timestampms": 1598848293384, + "type": "sell" + }, + { + "amount": "0.0004638", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369967, + "timestamp": 1598848293, + "timestampms": 1598848293359, + "type": "buy" + }, + { + "amount": "0.0006568", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369961, + "timestamp": 1598848283, + "timestampms": 1598848283208, + "type": "sell" + }, + { + "amount": "0.000253", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369956, + "timestamp": 1598848283, + "timestampms": 1598848283184, + "type": "buy" + }, + { + "amount": "0.0004052", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369947, + "timestamp": 1598848273, + "timestampms": 1598848273048, + "type": "sell" + }, + { + "amount": "0.0000892", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369942, + "timestamp": 1598848273, + "timestampms": 1598848273012, + "type": "buy" + }, + { + "amount": "0.0000415", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369933, + "timestamp": 1598848262, + "timestampms": 1598848262881, + "type": "sell" + }, + { + "amount": "0.0005369", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369928, + "timestamp": 1598848262, + "timestampms": 1598848262857, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369681, + "timestamp": 1598848252, + "timestampms": 1598848252733, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369673, + "timestamp": 1598848242, + "timestampms": 1598848242596, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369665, + "timestamp": 1598848232, + "timestampms": 1598848232444, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.24", + "tid": 642369659, + "timestamp": 1598848222, + "timestampms": 1598848222281, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369649, + "timestamp": 1598848212, + "timestampms": 1598848212148, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369641, + "timestamp": 1598848201, + "timestampms": 1598848201983, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369394, + "timestamp": 1598848191, + "timestampms": 1598848191833, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369386, + "timestamp": 1598848181, + "timestampms": 1598848181694, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369378, + "timestamp": 1598848171, + "timestampms": 1598848171451, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369372, + "timestamp": 1598848161, + "timestampms": 1598848161307, + "type": "buy" + }, + { + "amount": "0.0007977", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369363, + "timestamp": 1598848151, + "timestampms": 1598848151049, + "type": "sell" + }, + { + "amount": "0.0009776", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369358, + "timestamp": 1598848151, + "timestampms": 1598848151016, + "type": "buy" + }, + { + "amount": "0.0006412", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369349, + "timestamp": 1598848140, + "timestampms": 1598848140866, + "type": "sell" + }, + { + "amount": "0.0007287", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369344, + "timestamp": 1598848140, + "timestampms": 1598848140840, + "type": "buy" + }, + { + "amount": "0.0002288", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369101, + "timestamp": 1598848130, + "timestampms": 1598848130486, + "type": "sell" + }, + { + "amount": "0.0006634", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369096, + "timestamp": 1598848130, + "timestampms": 1598848130461, + "type": "buy" + }, + { + "amount": "0.0006886", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369090, + "timestamp": 1598848120, + "timestampms": 1598848120314, + "type": "sell" + }, + { + "amount": "0.000879", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369085, + "timestamp": 1598848120, + "timestampms": 1598848120289, + "type": "buy" + }, + { + "amount": "0.000585", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369077, + "timestamp": 1598848110, + "timestampms": 1598848110154, + "type": "sell" + }, + { + "amount": "0.0003618", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369072, + "timestamp": 1598848110, + "timestampms": 1598848110129, + "type": "buy" + }, + { + "amount": "0.0003633", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369064, + "timestamp": 1598848099, + "timestampms": 1598848099993, + "type": "sell" + }, + { + "amount": "0.0003905", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369059, + "timestamp": 1598848099, + "timestampms": 1598848099967, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369051, + "timestamp": 1598848089, + "timestampms": 1598848089832, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369043, + "timestamp": 1598848079, + "timestampms": 1598848079702, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368790, + "timestamp": 1598848069, + "timestampms": 1598848069569, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368784, + "timestamp": 1598848059, + "timestampms": 1598848059279, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368776, + "timestamp": 1598848049, + "timestampms": 1598848049153, + "type": "buy" + }, + { + "amount": "0.000479", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368768, + "timestamp": 1598848038, + "timestampms": 1598848038994, + "type": "sell" + }, + { + "amount": "0.0008482", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368763, + "timestamp": 1598848038, + "timestampms": 1598848038964, + "type": "buy" + }, + { + "amount": "0.0008144", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368756, + "timestamp": 1598848028, + "timestampms": 1598848028834, + "type": "sell" + }, + { + "amount": "0.0001039", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368751, + "timestamp": 1598848028, + "timestampms": 1598848028807, + "type": "buy" + }, + { + "amount": "0.0000404", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368742, + "timestamp": 1598848018, + "timestampms": 1598848018673, + "type": "sell" + }, + { + "amount": "0.0003341", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368737, + "timestamp": 1598848018, + "timestampms": 1598848018647, + "type": "buy" + }, + { + "amount": "1.523391", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368568, + "timestamp": 1598848010, + "timestampms": 1598848010368, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368501, + "timestamp": 1598848008, + "timestampms": 1598848008510, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368495, + "timestamp": 1598847998, + "timestampms": 1598847998312, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368487, + "timestamp": 1598847988, + "timestampms": 1598847988165, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368479, + "timestamp": 1598847978, + "timestampms": 1598847978036, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368471, + "timestamp": 1598847967, + "timestampms": 1598847967889, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368463, + "timestamp": 1598847957, + "timestampms": 1598847957763, + "type": "buy" + }, + { + "amount": "0.472609", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368360, + "timestamp": 1598847953, + "timestampms": 1598847953333, + "type": "buy" + }, + { + "amount": "0.032101", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368355, + "timestamp": 1598847953, + "timestampms": 1598847953309, + "type": "buy" + }, + { + "amount": "0.063582", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368350, + "timestamp": 1598847953, + "timestampms": 1598847953284, + "type": "buy" + }, + { + "amount": "0.255298", + "exchange": "gemini", + "price": "11690.22", + "tid": 642368291, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.4994", + "exchange": "gemini", + "price": "11690.23", + "tid": 642368289, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.4942", + "exchange": "gemini", + "price": "11690.24", + "tid": 642368287, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.046436", + "exchange": "gemini", + "price": "11690.25", + "tid": 642368285, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.136374", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368283, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.063626", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368278, + "timestamp": 1598847949, + "timestampms": 1598847949338, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368211, + "timestamp": 1598847947, + "timestampms": 1598847947611, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368205, + "timestamp": 1598847937, + "timestampms": 1598847937343, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368197, + "timestamp": 1598847927, + "timestampms": 1598847927214, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368189, + "timestamp": 1598847917, + "timestampms": 1598847917080, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.84", + "tid": 642368182, + "timestamp": 1598847906, + "timestampms": 1598847906946, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.84", + "tid": 642368173, + "timestamp": 1598847896, + "timestampms": 1598847896813, + "type": "buy" + }, + { + "amount": "0.0004696", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367924, + "timestamp": 1598847886, + "timestampms": 1598847886677, + "type": "sell" + }, + { + "amount": "0.0007677", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367919, + "timestamp": 1598847886, + "timestampms": 1598847886648, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367913, + "timestamp": 1598847876, + "timestampms": 1598847876314, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367904, + "timestamp": 1598847866, + "timestampms": 1598847866163, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367896, + "timestamp": 1598847856, + "timestampms": 1598847856039, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367887, + "timestamp": 1598847845, + "timestampms": 1598847845919, + "type": "buy" + }, + { + "amount": "0.0002559", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367878, + "timestamp": 1598847835, + "timestampms": 1598847835789, + "type": "sell" + }, + { + "amount": "0.0004689", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367873, + "timestamp": 1598847835, + "timestampms": 1598847835764, + "type": "buy" + }, + { + "amount": "0.03464", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367692, + "timestamp": 1598847827, + "timestampms": 1598847827147, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367626, + "timestamp": 1598847825, + "timestampms": 1598847825624, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367619, + "timestamp": 1598847815, + "timestampms": 1598847815347, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367611, + "timestamp": 1598847805, + "timestampms": 1598847805216, + "type": "sell" + }, + { + "amount": "0.0004673", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367602, + "timestamp": 1598847795, + "timestampms": 1598847795088, + "type": "sell" + }, + { + "amount": "0.0004929", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367597, + "timestamp": 1598847795, + "timestampms": 1598847795051, + "type": "buy" + }, + { + "amount": "0.0006385", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367591, + "timestamp": 1598847784, + "timestampms": 1598847784911, + "type": "sell" + }, + { + "amount": "0.000777", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367586, + "timestamp": 1598847784, + "timestampms": 1598847784886, + "type": "buy" + }, + { + "amount": "0.0004177", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367576, + "timestamp": 1598847774, + "timestampms": 1598847774753, + "type": "sell" + }, + { + "amount": "0.0000148", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367571, + "timestamp": 1598847774, + "timestampms": 1598847774728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367329, + "timestamp": 1598847764, + "timestampms": 1598847764594, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367322, + "timestamp": 1598847754, + "timestampms": 1598847754324, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367314, + "timestamp": 1598847744, + "timestampms": 1598847744186, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367304, + "timestamp": 1598847734, + "timestampms": 1598847734045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367298, + "timestamp": 1598847723, + "timestampms": 1598847723789, + "type": "buy" + }, + { + "amount": "0.0006687", + "exchange": "gemini", + "price": "11694.17", + "tid": 642367289, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.00001", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367287, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.00001", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367285, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.0008684", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367280, + "timestamp": 1598847713, + "timestampms": 1598847713627, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367047, + "timestamp": 1598847703, + "timestampms": 1598847703492, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367040, + "timestamp": 1598847693, + "timestampms": 1598847693251, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367032, + "timestamp": 1598847683, + "timestampms": 1598847683118, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367023, + "timestamp": 1598847672, + "timestampms": 1598847672986, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11701.08", + "tid": 642367017, + "timestamp": 1598847662, + "timestampms": 1598847662851, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11701.08", + "tid": 642367007, + "timestamp": 1598847652, + "timestampms": 1598847652694, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366749, + "timestamp": 1598847642, + "timestampms": 1598847642562, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366742, + "timestamp": 1598847632, + "timestampms": 1598847632424, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366734, + "timestamp": 1598847622, + "timestampms": 1598847622290, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366724, + "timestamp": 1598847612, + "timestampms": 1598847612156, + "type": "buy" + }, + { + "amount": "0.0008005", + "exchange": "gemini", + "price": "11699.29", + "tid": 642366718, + "timestamp": 1598847601, + "timestampms": 1598847601994, + "type": "sell" + }, + { + "amount": "0.0005064", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366713, + "timestamp": 1598847601, + "timestampms": 1598847601970, + "type": "buy" + }, + { + "amount": "0.0001031", + "exchange": "gemini", + "price": "11699.29", + "tid": 642366704, + "timestamp": 1598847591, + "timestampms": 1598847591844, + "type": "sell" + }, + { + "amount": "0.0003043", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366699, + "timestamp": 1598847591, + "timestampms": 1598847591817, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366451, + "timestamp": 1598847581, + "timestampms": 1598847581676, + "type": "buy" + } + ], + "queryString": "limit_trades=500", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382614, + "timestamp": 1598850933, + "timestampms": 1598850933484, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382608, + "timestamp": 1598850923, + "timestampms": 1598850923336, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382599, + "timestamp": 1598850913, + "timestampms": 1598850913194, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382590, + "timestamp": 1598850903, + "timestampms": 1598850903045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.61", + "tid": 642382583, + "timestamp": 1598850892, + "timestampms": 1598850892900, + "type": "buy" + }, + { + "amount": "0.0004687", + "exchange": "gemini", + "price": "11673.73", + "tid": 642382356, + "timestamp": 1598850882, + "timestampms": 1598850882772, + "type": "sell" + }, + { + "amount": "0.0005692", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382348, + "timestamp": 1598850882, + "timestampms": 1598850882747, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382322, + "timestamp": 1598850872, + "timestampms": 1598850872576, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382316, + "timestamp": 1598850862, + "timestampms": 1598850862450, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382306, + "timestamp": 1598850852, + "timestampms": 1598850852315, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382298, + "timestamp": 1598850842, + "timestampms": 1598850842188, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.85", + "tid": 642382291, + "timestamp": 1598850832, + "timestampms": 1598850832057, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.63", + "tid": 642382097, + "timestamp": 1598850821, + "timestampms": 1598850821925, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382035, + "timestamp": 1598850811, + "timestampms": 1598850811791, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382029, + "timestamp": 1598850801, + "timestampms": 1598850801664, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382020, + "timestamp": 1598850791, + "timestampms": 1598850791539, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382011, + "timestamp": 1598850781, + "timestampms": 1598850781412, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.19", + "tid": 642382004, + "timestamp": 1598850771, + "timestampms": 1598850771281, + "type": "buy" + }, + { + "amount": "0.0004377", + "exchange": "gemini", + "price": "11673.63", + "tid": 642381841, + "timestamp": 1598850761, + "timestampms": 1598850761036, + "type": "sell" + }, + { + "amount": "0.0009182", + "exchange": "gemini", + "price": "11674.19", + "tid": 642381833, + "timestamp": 1598850761, + "timestampms": 1598850761008, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381749, + "timestamp": 1598850750, + "timestampms": 1598850750865, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381741, + "timestamp": 1598850740, + "timestampms": 1598850740720, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381733, + "timestamp": 1598850730, + "timestampms": 1598850730596, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381725, + "timestamp": 1598850720, + "timestampms": 1598850720462, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.09", + "tid": 642381716, + "timestamp": 1598850710, + "timestampms": 1598850710332, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381579, + "timestamp": 1598850700, + "timestampms": 1598850700060, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381458, + "timestamp": 1598850689, + "timestampms": 1598850689923, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381450, + "timestamp": 1598850679, + "timestampms": 1598850679682, + "type": "buy" + }, + { + "amount": "0.0009278", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381443, + "timestamp": 1598850669, + "timestampms": 1598850669549, + "type": "sell" + }, + { + "amount": "0.0003379", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381438, + "timestamp": 1598850669, + "timestampms": 1598850669521, + "type": "buy" + }, + { + "amount": "0.0007846", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381429, + "timestamp": 1598850659, + "timestampms": 1598850659378, + "type": "sell" + }, + { + "amount": "0.0008162", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381424, + "timestamp": 1598850659, + "timestampms": 1598850659352, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.10", + "tid": 642381415, + "timestamp": 1598850649, + "timestampms": 1598850649213, + "type": "buy" + }, + { + "amount": "0.0006557", + "exchange": "gemini", + "price": "11672.47", + "tid": 642381289, + "timestamp": 1598850639, + "timestampms": 1598850639081, + "type": "sell" + }, + { + "amount": "0.0008514", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381281, + "timestamp": 1598850639, + "timestampms": 1598850639058, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381156, + "timestamp": 1598850628, + "timestampms": 1598850628922, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381148, + "timestamp": 1598850618, + "timestampms": 1598850618784, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381140, + "timestamp": 1598850608, + "timestampms": 1598850608650, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381132, + "timestamp": 1598850598, + "timestampms": 1598850598513, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381123, + "timestamp": 1598850588, + "timestampms": 1598850588220, + "type": "buy" + }, + { + "amount": "0.0004102", + "exchange": "gemini", + "price": "11672.46", + "tid": 642381009, + "timestamp": 1598850578, + "timestampms": 1598850578084, + "type": "sell" + }, + { + "amount": "0.0004516", + "exchange": "gemini", + "price": "11672.67", + "tid": 642381004, + "timestamp": 1598850578, + "timestampms": 1598850578058, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380888, + "timestamp": 1598850567, + "timestampms": 1598850567923, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380880, + "timestamp": 1598850557, + "timestampms": 1598850557779, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380873, + "timestamp": 1598850547, + "timestampms": 1598850547648, + "type": "buy" + }, + { + "amount": "0.000556", + "exchange": "gemini", + "price": "11673.70", + "tid": 642380864, + "timestamp": 1598850537, + "timestampms": 1598850537513, + "type": "buy" + }, + { + "amount": "0.001444", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380862, + "timestamp": 1598850537, + "timestampms": 1598850537513, + "type": "buy" + }, + { + "amount": "0.000278", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380853, + "timestamp": 1598850527, + "timestampms": 1598850527379, + "type": "buy" + }, + { + "amount": "0.001722", + "exchange": "gemini", + "price": "11673.69", + "tid": 642380851, + "timestamp": 1598850527, + "timestampms": 1598850527379, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380719, + "timestamp": 1598850517, + "timestampms": 1598850517088, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380585, + "timestamp": 1598850506, + "timestampms": 1598850506955, + "type": "buy" + }, + { + "amount": "0.0008279", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380577, + "timestamp": 1598850496, + "timestampms": 1598850496810, + "type": "sell" + }, + { + "amount": "0.0001668", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380572, + "timestamp": 1598850496, + "timestampms": 1598850496786, + "type": "buy" + }, + { + "amount": "0.000103", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380564, + "timestamp": 1598850486, + "timestampms": 1598850486626, + "type": "sell" + }, + { + "amount": "0.000036", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380559, + "timestamp": 1598850486, + "timestampms": 1598850486602, + "type": "buy" + }, + { + "amount": "0.0003708", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380550, + "timestamp": 1598850476, + "timestampms": 1598850476470, + "type": "sell" + }, + { + "amount": "0.0002739", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380545, + "timestamp": 1598850476, + "timestampms": 1598850476447, + "type": "buy" + }, + { + "amount": "0.0005922", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380537, + "timestamp": 1598850466, + "timestampms": 1598850466303, + "type": "sell" + }, + { + "amount": "0.000113", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380532, + "timestamp": 1598850466, + "timestampms": 1598850466278, + "type": "buy" + }, + { + "amount": "0.0001031", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380406, + "timestamp": 1598850456, + "timestampms": 1598850456001, + "type": "sell" + }, + { + "amount": "0.0006239", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380401, + "timestamp": 1598850455, + "timestampms": 1598850455976, + "type": "buy" + }, + { + "amount": "0.0007953", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380275, + "timestamp": 1598850445, + "timestampms": 1598850445838, + "type": "sell" + }, + { + "amount": "0.0000845", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380270, + "timestamp": 1598850445, + "timestampms": 1598850445814, + "type": "buy" + }, + { + "amount": "0.0009655", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380261, + "timestamp": 1598850435, + "timestampms": 1598850435687, + "type": "sell" + }, + { + "amount": "0.000135", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380256, + "timestamp": 1598850435, + "timestampms": 1598850435662, + "type": "buy" + }, + { + "amount": "0.0007829", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380250, + "timestamp": 1598850425, + "timestampms": 1598850425537, + "type": "sell" + }, + { + "amount": "0.0007139", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380245, + "timestamp": 1598850425, + "timestampms": 1598850425513, + "type": "buy" + }, + { + "amount": "0.0001776", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380235, + "timestamp": 1598850415, + "timestampms": 1598850415374, + "type": "sell" + }, + { + "amount": "0.0001376", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380230, + "timestamp": 1598850415, + "timestampms": 1598850415350, + "type": "buy" + }, + { + "amount": "0.0001576", + "exchange": "gemini", + "price": "11669.92", + "tid": 642380222, + "timestamp": 1598850405, + "timestampms": 1598850405224, + "type": "sell" + }, + { + "amount": "0.0005596", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380217, + "timestamp": 1598850405, + "timestampms": 1598850405200, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.93", + "tid": 642380091, + "timestamp": 1598850395, + "timestampms": 1598850395060, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379961, + "timestamp": 1598850384, + "timestampms": 1598850384924, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379951, + "timestamp": 1598850374, + "timestampms": 1598850374798, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379945, + "timestamp": 1598850364, + "timestampms": 1598850364666, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379936, + "timestamp": 1598850354, + "timestampms": 1598850354526, + "type": "buy" + }, + { + "amount": "0.0009645", + "exchange": "gemini", + "price": "11669.16", + "tid": 642379928, + "timestamp": 1598850344, + "timestampms": 1598850344403, + "type": "sell" + }, + { + "amount": "0.0001812", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379923, + "timestamp": 1598850344, + "timestampms": 1598850344379, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.84", + "tid": 642379812, + "timestamp": 1598850334, + "timestampms": 1598850334251, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379690, + "timestamp": 1598850324, + "timestampms": 1598850324122, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379681, + "timestamp": 1598850313, + "timestampms": 1598850313988, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379675, + "timestamp": 1598850303, + "timestampms": 1598850303858, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379665, + "timestamp": 1598850293, + "timestampms": 1598850293614, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.92", + "tid": 642379657, + "timestamp": 1598850283, + "timestampms": 1598850283474, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379539, + "timestamp": 1598850273, + "timestampms": 1598850273337, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379425, + "timestamp": 1598850263, + "timestampms": 1598850263198, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379415, + "timestamp": 1598850253, + "timestampms": 1598850253047, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379409, + "timestamp": 1598850242, + "timestampms": 1598850242886, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379400, + "timestamp": 1598850232, + "timestampms": 1598850232657, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.79", + "tid": 642379392, + "timestamp": 1598850222, + "timestampms": 1598850222532, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379263, + "timestamp": 1598850212, + "timestampms": 1598850212403, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379129, + "timestamp": 1598850202, + "timestampms": 1598850202277, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379120, + "timestamp": 1598850192, + "timestampms": 1598850192151, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379114, + "timestamp": 1598850181, + "timestampms": 1598850181998, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379104, + "timestamp": 1598850171, + "timestampms": 1598850171688, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11661.12", + "tid": 642379096, + "timestamp": 1598850161, + "timestampms": 1598850161554, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378964, + "timestamp": 1598850151, + "timestampms": 1598850151412, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378832, + "timestamp": 1598850141, + "timestampms": 1598850141273, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378822, + "timestamp": 1598850131, + "timestampms": 1598850131118, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378816, + "timestamp": 1598850120, + "timestampms": 1598850120980, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378807, + "timestamp": 1598850110, + "timestampms": 1598850110733, + "type": "buy" + }, + { + "amount": "0.0007051", + "exchange": "gemini", + "price": "11660.00", + "tid": 642378799, + "timestamp": 1598850100, + "timestampms": 1598850100603, + "type": "sell" + }, + { + "amount": "0.0001487", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378794, + "timestamp": 1598850100, + "timestampms": 1598850100578, + "type": "buy" + }, + { + "amount": "0.0004598", + "exchange": "gemini", + "price": "11660.00", + "tid": 642378674, + "timestamp": 1598850090, + "timestampms": 1598850090454, + "type": "sell" + }, + { + "amount": "0.0001629", + "exchange": "gemini", + "price": "11660.01", + "tid": 642378669, + "timestamp": 1598850090, + "timestampms": 1598850090428, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11662.19", + "tid": 642378610, + "timestamp": 1598850088, + "timestampms": 1598850088243, + "type": "sell" + }, + { + "amount": "0.192", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378608, + "timestamp": 1598850088, + "timestampms": 1598850088243, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378540, + "timestamp": 1598850080, + "timestampms": 1598850080304, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378531, + "timestamp": 1598850070, + "timestampms": 1598850070158, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378523, + "timestamp": 1598850060, + "timestampms": 1598850060026, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.20", + "tid": 642378515, + "timestamp": 1598850049, + "timestampms": 1598850049781, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11665.35", + "tid": 642378507, + "timestamp": 1598850039, + "timestampms": 1598850039647, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11662.48", + "tid": 642378384, + "timestamp": 1598850029, + "timestampms": 1598850029519, + "type": "sell" + }, + { + "amount": "0.135589", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378323, + "timestamp": 1598850026, + "timestampms": 1598850026998, + "type": "sell" + }, + { + "amount": "0.059484", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378318, + "timestamp": 1598850026, + "timestampms": 1598850026974, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11667.83", + "tid": 642378255, + "timestamp": 1598850019, + "timestampms": 1598850019381, + "type": "buy" + }, + { + "amount": "0.001923", + "exchange": "gemini", + "price": "11666.12", + "tid": 642378245, + "timestamp": 1598850009, + "timestampms": 1598850009249, + "type": "sell" + }, + { + "amount": "0.000077", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378243, + "timestamp": 1598850009, + "timestampms": 1598850009249, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378236, + "timestamp": 1598849999, + "timestampms": 1598849999112, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378228, + "timestamp": 1598849988, + "timestampms": 1598849988977, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378220, + "timestamp": 1598849978, + "timestampms": 1598849978847, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.58", + "tid": 642378094, + "timestamp": 1598849968, + "timestampms": 1598849968712, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377966, + "timestamp": 1598849958, + "timestampms": 1598849958583, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377957, + "timestamp": 1598849948, + "timestampms": 1598849948443, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377949, + "timestamp": 1598849938, + "timestampms": 1598849938314, + "type": "buy" + }, + { + "amount": "0.0001767", + "exchange": "gemini", + "price": "11666.38", + "tid": 642377941, + "timestamp": 1598849928, + "timestampms": 1598849928173, + "type": "sell" + }, + { + "amount": "0.0006903", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377936, + "timestamp": 1598849928, + "timestampms": 1598849928148, + "type": "buy" + }, + { + "amount": "0.0004407", + "exchange": "gemini", + "price": "11666.38", + "tid": 642377928, + "timestamp": 1598849918, + "timestampms": 1598849918019, + "type": "sell" + }, + { + "amount": "0.0005044", + "exchange": "gemini", + "price": "11669.71", + "tid": 642377923, + "timestamp": 1598849917, + "timestampms": 1598849917988, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11670.29", + "tid": 642377800, + "timestamp": 1598849907, + "timestampms": 1598849907844, + "type": "buy" + }, + { + "amount": "0.0043675", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377735, + "timestamp": 1598849904, + "timestampms": 1598849904696, + "type": "sell" + }, + { + "amount": "0.0006755", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377673, + "timestamp": 1598849897, + "timestampms": 1598849897712, + "type": "sell" + }, + { + "amount": "0.0013245", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377671, + "timestamp": 1598849897, + "timestampms": 1598849897712, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377661, + "timestamp": 1598849887, + "timestampms": 1598849887583, + "type": "sell" + }, + { + "amount": "0.0006439", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377654, + "timestamp": 1598849877, + "timestampms": 1598849877447, + "type": "sell" + }, + { + "amount": "0.0007116", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377649, + "timestamp": 1598849877, + "timestampms": 1598849877424, + "type": "buy" + }, + { + "amount": "0.0004047", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377641, + "timestamp": 1598849867, + "timestampms": 1598849867275, + "type": "sell" + }, + { + "amount": "0.0001902", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377636, + "timestamp": 1598849867, + "timestampms": 1598849867248, + "type": "buy" + }, + { + "amount": "0.0005595", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377628, + "timestamp": 1598849857, + "timestampms": 1598849857116, + "type": "sell" + }, + { + "amount": "0.000024", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377623, + "timestamp": 1598849857, + "timestampms": 1598849857090, + "type": "buy" + }, + { + "amount": "0.0001104", + "exchange": "gemini", + "price": "11670.76", + "tid": 642377506, + "timestamp": 1598849846, + "timestampms": 1598849846967, + "type": "sell" + }, + { + "amount": "0.0006308", + "exchange": "gemini", + "price": "11670.77", + "tid": 642377501, + "timestamp": 1598849846, + "timestampms": 1598849846941, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11670.97", + "tid": 642377436, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.015212", + "exchange": "gemini", + "price": "11671.14", + "tid": 642377434, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.035291", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377432, + "timestamp": 1598849843, + "timestampms": 1598849843536, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377367, + "timestamp": 1598849836, + "timestampms": 1598849836806, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377358, + "timestamp": 1598849826, + "timestampms": 1598849826685, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377350, + "timestamp": 1598849816, + "timestampms": 1598849816553, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377342, + "timestamp": 1598849806, + "timestampms": 1598849806400, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377334, + "timestamp": 1598849796, + "timestampms": 1598849796250, + "type": "sell" + }, + { + "amount": "0.0001237", + "exchange": "gemini", + "price": "11675.04", + "tid": 642377212, + "timestamp": 1598849786, + "timestampms": 1598849786115, + "type": "sell" + }, + { + "amount": "0.0006136", + "exchange": "gemini", + "price": "11675.05", + "tid": 642377204, + "timestamp": 1598849786, + "timestampms": 1598849786091, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377073, + "timestamp": 1598849775, + "timestampms": 1598849775948, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377062, + "timestamp": 1598849765, + "timestampms": 1598849765809, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377055, + "timestamp": 1598849755, + "timestampms": 1598849755671, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377047, + "timestamp": 1598849745, + "timestampms": 1598849745515, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11675.45", + "tid": 642377039, + "timestamp": 1598849735, + "timestampms": 1598849735386, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.93", + "tid": 642376938, + "timestamp": 1598849725, + "timestampms": 1598849725263, + "type": "buy" + }, + { + "amount": "0.1", + "exchange": "gemini", + "price": "11671.31", + "tid": 642376780, + "timestamp": 1598849716, + "timestampms": 1598849716657, + "type": "sell" + }, + { + "amount": "0.057156", + "exchange": "gemini", + "price": "11673.93", + "tid": 642376775, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.026422", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376773, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.016422", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376771, + "timestamp": 1598849716, + "timestampms": 1598849716454, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376764, + "timestamp": 1598849715, + "timestampms": 1598849715126, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376756, + "timestamp": 1598849704, + "timestampms": 1598849704972, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376748, + "timestamp": 1598849694, + "timestampms": 1598849694844, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376740, + "timestamp": 1598849684, + "timestampms": 1598849684709, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.92", + "tid": 642376732, + "timestamp": 1598849674, + "timestampms": 1598849674523, + "type": "buy" + }, + { + "amount": "0.000881", + "exchange": "gemini", + "price": "11671.31", + "tid": 642376663, + "timestamp": 1598849664, + "timestampms": 1598849664401, + "type": "sell" + }, + { + "amount": "0.000555", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376655, + "timestamp": 1598849664, + "timestampms": 1598849664377, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376471, + "timestamp": 1598849654, + "timestampms": 1598849654238, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376463, + "timestamp": 1598849644, + "timestampms": 1598849644105, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376456, + "timestamp": 1598849633, + "timestampms": 1598849633982, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376448, + "timestamp": 1598849623, + "timestampms": 1598849623810, + "type": "buy" + }, + { + "amount": "0.0009903", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376440, + "timestamp": 1598849613, + "timestampms": 1598849613676, + "type": "sell" + }, + { + "amount": "0.0005454", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376435, + "timestamp": 1598849613, + "timestampms": 1598849613651, + "type": "buy" + }, + { + "amount": "0.0008607", + "exchange": "gemini", + "price": "11671.80", + "tid": 642376390, + "timestamp": 1598849603, + "timestampms": 1598849603501, + "type": "sell" + }, + { + "amount": "0.0001283", + "exchange": "gemini", + "price": "11673.29", + "tid": 642376382, + "timestamp": 1598849603, + "timestampms": 1598849603477, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376181, + "timestamp": 1598849593, + "timestampms": 1598849593341, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376172, + "timestamp": 1598849583, + "timestampms": 1598849583216, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376165, + "timestamp": 1598849573, + "timestampms": 1598849573077, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376157, + "timestamp": 1598849562, + "timestampms": 1598849562928, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376149, + "timestamp": 1598849552, + "timestampms": 1598849552785, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11673.45", + "tid": 642376134, + "timestamp": 1598849542, + "timestampms": 1598849542654, + "type": "buy" + }, + { + "amount": "0.1569041", + "exchange": "gemini", + "price": "11669.39", + "tid": 642375912, + "timestamp": 1598849537, + "timestampms": 1598849537285, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11669.19", + "tid": 642375910, + "timestamp": 1598849537, + "timestampms": 1598849537284, + "type": "buy" + }, + { + "amount": "0.0430959", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375908, + "timestamp": 1598849537, + "timestampms": 1598849537284, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375900, + "timestamp": 1598849532, + "timestampms": 1598849532516, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375892, + "timestamp": 1598849522, + "timestampms": 1598849522392, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375885, + "timestamp": 1598849512, + "timestampms": 1598849512249, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375877, + "timestamp": 1598849502, + "timestampms": 1598849502084, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375869, + "timestamp": 1598849491, + "timestampms": 1598849491951, + "type": "buy" + }, + { + "amount": "0.0009811", + "exchange": "gemini", + "price": "11667.07", + "tid": 642375863, + "timestamp": 1598849481, + "timestampms": 1598849481820, + "type": "sell" + }, + { + "amount": "0.0005331", + "exchange": "gemini", + "price": "11669.18", + "tid": 642375858, + "timestamp": 1598849481, + "timestampms": 1598849481796, + "type": "buy" + }, + { + "amount": "0.0019642", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375692, + "timestamp": 1598849476, + "timestampms": 1598849476759, + "type": "sell" + }, + { + "amount": "1.0834", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375687, + "timestamp": 1598849476, + "timestampms": 1598849476736, + "type": "sell" + }, + { + "amount": "0.9146358", + "exchange": "gemini", + "price": "11671.46", + "tid": 642375682, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.95", + "exchange": "gemini", + "price": "11672.60", + "tid": 642375680, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.1353642", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375678, + "timestamp": 1598849476, + "timestampms": 1598849476712, + "type": "sell" + }, + { + "amount": "0.055566", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375673, + "timestamp": 1598849476, + "timestampms": 1598849476686, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375606, + "timestamp": 1598849471, + "timestampms": 1598849471659, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375597, + "timestamp": 1598849461, + "timestampms": 1598849461522, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375590, + "timestamp": 1598849451, + "timestampms": 1598849451386, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375582, + "timestamp": 1598849441, + "timestampms": 1598849441233, + "type": "sell" + }, + { + "amount": "0.0003074", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375574, + "timestamp": 1598849431, + "timestampms": 1598849431089, + "type": "sell" + }, + { + "amount": "0.0000432", + "exchange": "gemini", + "price": "11674.88", + "tid": 642375569, + "timestamp": 1598849431, + "timestampms": 1598849431065, + "type": "buy" + }, + { + "amount": "0.0007624", + "exchange": "gemini", + "price": "11672.61", + "tid": 642375563, + "timestamp": 1598849420, + "timestampms": 1598849420933, + "type": "sell" + }, + { + "amount": "0.0009046", + "exchange": "gemini", + "price": "11674.88", + "tid": 642375558, + "timestamp": 1598849420, + "timestampms": 1598849420908, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375323, + "timestamp": 1598849410, + "timestampms": 1598849410765, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375315, + "timestamp": 1598849400, + "timestampms": 1598849400634, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375306, + "timestamp": 1598849390, + "timestampms": 1598849390359, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375300, + "timestamp": 1598849380, + "timestampms": 1598849380229, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375292, + "timestamp": 1598849370, + "timestampms": 1598849370097, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11674.71", + "tid": 642375284, + "timestamp": 1598849359, + "timestampms": 1598849359868, + "type": "buy" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11668.96", + "tid": 642375075, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11668.92", + "tid": 642375073, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "0.148428", + "exchange": "gemini", + "price": "11668.38", + "tid": 642375071, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "0.10492", + "exchange": "gemini", + "price": "11667.05", + "tid": 642375069, + "timestamp": 1598849353, + "timestampms": 1598849353983, + "type": "buy" + }, + { + "amount": "1.425161", + "exchange": "gemini", + "price": "11667.05", + "tid": 642375064, + "timestamp": 1598849353, + "timestampms": 1598849353957, + "type": "buy" + }, + { + "amount": "0.574839", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375062, + "timestamp": 1598849353, + "timestampms": 1598849353957, + "type": "buy" + }, + { + "amount": "0.1677", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375057, + "timestamp": 1598849353, + "timestampms": 1598849353932, + "type": "buy" + }, + { + "amount": "0.146959", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375052, + "timestamp": 1598849353, + "timestampms": 1598849353907, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375047, + "timestamp": 1598849349, + "timestampms": 1598849349726, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375038, + "timestamp": 1598849339, + "timestampms": 1598849339574, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375029, + "timestamp": 1598849329, + "timestampms": 1598849329315, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375023, + "timestamp": 1598849319, + "timestampms": 1598849319190, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11663.81", + "tid": 642375015, + "timestamp": 1598849309, + "timestampms": 1598849309062, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11666.29", + "tid": 642375007, + "timestamp": 1598849298, + "timestampms": 1598849298815, + "type": "buy" + }, + { + "amount": "0.488", + "exchange": "gemini", + "price": "11669.76", + "tid": 642374864, + "timestamp": 1598849293, + "timestampms": 1598849293430, + "type": "sell" + }, + { + "amount": "2.543086", + "exchange": "gemini", + "price": "11671.50", + "tid": 642374862, + "timestamp": 1598849293, + "timestampms": 1598849293430, + "type": "sell" + }, + { + "amount": "1.356914", + "exchange": "gemini", + "price": "11671.50", + "tid": 642374857, + "timestamp": 1598849293, + "timestampms": 1598849293406, + "type": "sell" + }, + { + "amount": "0.643086", + "exchange": "gemini", + "price": "11672.00", + "tid": 642374855, + "timestamp": 1598849293, + "timestampms": 1598849293406, + "type": "sell" + }, + { + "amount": "0.353914", + "exchange": "gemini", + "price": "11672.00", + "tid": 642374850, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "1.9491", + "exchange": "gemini", + "price": "11672.90", + "tid": 642374848, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.007", + "exchange": "gemini", + "price": "11675.00", + "tid": 642374846, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11675.60", + "tid": 642374844, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.105886", + "exchange": "gemini", + "price": "11675.61", + "tid": 642374842, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.08543", + "exchange": "gemini", + "price": "11676.36", + "tid": 642374840, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "0.194168", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374838, + "timestamp": 1598849293, + "timestampms": 1598849293383, + "type": "sell" + }, + { + "amount": "1.446095", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374833, + "timestamp": 1598849293, + "timestampms": 1598849293359, + "type": "sell" + }, + { + "amount": "0.2", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374828, + "timestamp": 1598849293, + "timestampms": 1598849293335, + "type": "sell" + }, + { + "amount": "0.149737", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374823, + "timestamp": 1598849293, + "timestampms": 1598849293312, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374758, + "timestamp": 1598849288, + "timestampms": 1598849288687, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11677.30", + "tid": 642374750, + "timestamp": 1598849278, + "timestampms": 1598849278530, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374741, + "timestamp": 1598849268, + "timestampms": 1598849268391, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374735, + "timestamp": 1598849258, + "timestampms": 1598849258259, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374727, + "timestamp": 1598849248, + "timestampms": 1598849248119, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.39", + "tid": 642374719, + "timestamp": 1598849237, + "timestampms": 1598849237959, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374475, + "timestamp": 1598849227, + "timestampms": 1598849227825, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374466, + "timestamp": 1598849217, + "timestampms": 1598849217692, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374457, + "timestamp": 1598849207, + "timestampms": 1598849207563, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374451, + "timestamp": 1598849197, + "timestampms": 1598849197432, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374443, + "timestamp": 1598849187, + "timestampms": 1598849187309, + "type": "buy" + }, + { + "amount": "0.0005913", + "exchange": "gemini", + "price": "11676.36", + "tid": 642374435, + "timestamp": 1598849177, + "timestampms": 1598849177023, + "type": "sell" + }, + { + "amount": "0.0009976", + "exchange": "gemini", + "price": "11676.86", + "tid": 642374430, + "timestamp": 1598849177, + "timestampms": 1598849177000, + "type": "buy" + }, + { + "amount": "0.9914", + "exchange": "gemini", + "price": "11676.98", + "tid": 642374257, + "timestamp": 1598849171, + "timestampms": 1598849171204, + "type": "sell" + }, + { + "amount": "0.191467", + "exchange": "gemini", + "price": "11679.45", + "tid": 642374255, + "timestamp": 1598849171, + "timestampms": 1598849171203, + "type": "sell" + }, + { + "amount": "0.008533", + "exchange": "gemini", + "price": "11679.45", + "tid": 642374250, + "timestamp": 1598849171, + "timestampms": 1598849171179, + "type": "sell" + }, + { + "amount": "0.07914", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374248, + "timestamp": 1598849171, + "timestampms": 1598849171179, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374183, + "timestamp": 1598849166, + "timestampms": 1598849166869, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374175, + "timestamp": 1598849156, + "timestampms": 1598849156745, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374166, + "timestamp": 1598849146, + "timestampms": 1598849146605, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374160, + "timestamp": 1598849136, + "timestampms": 1598849136468, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374152, + "timestamp": 1598849126, + "timestampms": 1598849126338, + "type": "sell" + }, + { + "amount": "0.000177", + "exchange": "gemini", + "price": "11679.67", + "tid": 642374144, + "timestamp": 1598849116, + "timestampms": 1598849116176, + "type": "sell" + }, + { + "amount": "0.0001439", + "exchange": "gemini", + "price": "11683.70", + "tid": 642374139, + "timestamp": 1598849116, + "timestampms": 1598849116152, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11681.43", + "tid": 642373903, + "timestamp": 1598849105, + "timestampms": 1598849105909, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373893, + "timestamp": 1598849095, + "timestampms": 1598849095774, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373885, + "timestamp": 1598849085, + "timestampms": 1598849085636, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373879, + "timestamp": 1598849075, + "timestampms": 1598849075500, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373871, + "timestamp": 1598849065, + "timestampms": 1598849065368, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11686.32", + "tid": 642373861, + "timestamp": 1598849055, + "timestampms": 1598849055223, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373607, + "timestamp": 1598849045, + "timestampms": 1598849045076, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373598, + "timestamp": 1598849034, + "timestampms": 1598849034933, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373590, + "timestamp": 1598849024, + "timestampms": 1598849024788, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373584, + "timestamp": 1598849014, + "timestampms": 1598849014665, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373576, + "timestamp": 1598849004, + "timestampms": 1598849004540, + "type": "buy" + }, + { + "amount": "0.0002445", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373567, + "timestamp": 1598848994, + "timestampms": 1598848994411, + "type": "sell" + }, + { + "amount": "0.000227", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373562, + "timestamp": 1598848994, + "timestampms": 1598848994386, + "type": "buy" + }, + { + "amount": "0.0003115", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373316, + "timestamp": 1598848984, + "timestampms": 1598848984137, + "type": "sell" + }, + { + "amount": "0.0005039", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373311, + "timestamp": 1598848984, + "timestampms": 1598848984114, + "type": "buy" + }, + { + "amount": "0.0001642", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373301, + "timestamp": 1598848973, + "timestampms": 1598848973980, + "type": "sell" + }, + { + "amount": "0.0008888", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373296, + "timestamp": 1598848973, + "timestampms": 1598848973951, + "type": "buy" + }, + { + "amount": "0.0003519", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373288, + "timestamp": 1598848963, + "timestampms": 1598848963819, + "type": "sell" + }, + { + "amount": "0.0000126", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373283, + "timestamp": 1598848963, + "timestampms": 1598848963795, + "type": "buy" + }, + { + "amount": "0.0001933", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373277, + "timestamp": 1598848953, + "timestampms": 1598848953668, + "type": "sell" + }, + { + "amount": "0.0002974", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373272, + "timestamp": 1598848953, + "timestampms": 1598848953643, + "type": "buy" + }, + { + "amount": "0.0001316", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373264, + "timestamp": 1598848943, + "timestampms": 1598848943512, + "type": "sell" + }, + { + "amount": "0.0006548", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373259, + "timestamp": 1598848943, + "timestampms": 1598848943487, + "type": "buy" + }, + { + "amount": "0.0003662", + "exchange": "gemini", + "price": "11685.15", + "tid": 642373249, + "timestamp": 1598848933, + "timestampms": 1598848933357, + "type": "sell" + }, + { + "amount": "0.0006337", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373244, + "timestamp": 1598848933, + "timestampms": 1598848933331, + "type": "buy" + }, + { + "amount": "0.000218", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373010, + "timestamp": 1598848923, + "timestampms": 1598848923117, + "type": "buy" + }, + { + "amount": "0.001782", + "exchange": "gemini", + "price": "11685.16", + "tid": 642373008, + "timestamp": 1598848923, + "timestampms": 1598848923117, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372999, + "timestamp": 1598848912, + "timestampms": 1598848912994, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372991, + "timestamp": 1598848902, + "timestampms": 1598848902857, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372985, + "timestamp": 1598848892, + "timestampms": 1598848892719, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372977, + "timestamp": 1598848882, + "timestampms": 1598848882595, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11685.16", + "tid": 642372968, + "timestamp": 1598848872, + "timestampms": 1598848872466, + "type": "buy" + }, + { + "amount": "1.681266", + "exchange": "gemini", + "price": "11681.92", + "tid": 642372842, + "timestamp": 1598848870, + "timestampms": 1598848870038, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372722, + "timestamp": 1598848862, + "timestampms": 1598848862334, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372712, + "timestamp": 1598848852, + "timestampms": 1598848852187, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372704, + "timestamp": 1598848842, + "timestampms": 1598848842032, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372698, + "timestamp": 1598848831, + "timestampms": 1598848831897, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372690, + "timestamp": 1598848821, + "timestampms": 1598848821764, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11683.72", + "tid": 642372680, + "timestamp": 1598848811, + "timestampms": 1598848811624, + "type": "buy" + }, + { + "amount": "0.290189", + "exchange": "gemini", + "price": "11684.30", + "tid": 642372515, + "timestamp": 1598848804, + "timestampms": 1598848804719, + "type": "sell" + }, + { + "amount": "0.659811", + "exchange": "gemini", + "price": "11684.30", + "tid": 642372510, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "1.268271", + "exchange": "gemini", + "price": "11685.15", + "tid": 642372508, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "0.071918", + "exchange": "gemini", + "price": "11687.57", + "tid": 642372506, + "timestamp": 1598848804, + "timestampms": 1598848804694, + "type": "sell" + }, + { + "amount": "0.128082", + "exchange": "gemini", + "price": "11687.57", + "tid": 642372501, + "timestamp": 1598848804, + "timestampms": 1598848804669, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11687.93", + "tid": 642372436, + "timestamp": 1598848801, + "timestampms": 1598848801493, + "type": "sell" + }, + { + "amount": "0.00039", + "exchange": "gemini", + "price": "11687.93", + "tid": 642372427, + "timestamp": 1598848791, + "timestampms": 1598848791212, + "type": "sell" + }, + { + "amount": "0.00161", + "exchange": "gemini", + "price": "11688.15", + "tid": 642372425, + "timestamp": 1598848791, + "timestampms": 1598848791212, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11688.15", + "tid": 642372417, + "timestamp": 1598848781, + "timestampms": 1598848781060, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372411, + "timestamp": 1598848770, + "timestampms": 1598848770927, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372403, + "timestamp": 1598848760, + "timestampms": 1598848760780, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.20", + "tid": 642372394, + "timestamp": 1598848750, + "timestampms": 1598848750644, + "type": "buy" + }, + { + "amount": "0.028876", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372213, + "timestamp": 1598848743, + "timestampms": 1598848743590, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372148, + "timestamp": 1598848740, + "timestampms": 1598848740496, + "type": "sell" + }, + { + "amount": "0.0004446", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372139, + "timestamp": 1598848730, + "timestampms": 1598848730225, + "type": "sell" + }, + { + "amount": "0.000044", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372134, + "timestamp": 1598848730, + "timestampms": 1598848730200, + "type": "buy" + }, + { + "amount": "0.0001986", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372126, + "timestamp": 1598848720, + "timestampms": 1598848720079, + "type": "sell" + }, + { + "amount": "0.0008563", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372121, + "timestamp": 1598848720, + "timestampms": 1598848720055, + "type": "buy" + }, + { + "amount": "0.0009112", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372115, + "timestamp": 1598848709, + "timestampms": 1598848709919, + "type": "sell" + }, + { + "amount": "0.000712", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372110, + "timestamp": 1598848709, + "timestampms": 1598848709894, + "type": "buy" + }, + { + "amount": "0.000613", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372102, + "timestamp": 1598848699, + "timestampms": 1598848699769, + "type": "sell" + }, + { + "amount": "0.0000581", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372097, + "timestamp": 1598848699, + "timestampms": 1598848699745, + "type": "buy" + }, + { + "amount": "0.0008616", + "exchange": "gemini", + "price": "11690.21", + "tid": 642372087, + "timestamp": 1598848689, + "timestampms": 1598848689619, + "type": "sell" + }, + { + "amount": "0.0000267", + "exchange": "gemini", + "price": "11690.22", + "tid": 642372082, + "timestamp": 1598848689, + "timestampms": 1598848689591, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371835, + "timestamp": 1598848679, + "timestampms": 1598848679459, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371827, + "timestamp": 1598848669, + "timestampms": 1598848669330, + "type": "buy" + }, + { + "amount": "0.0001012", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371819, + "timestamp": 1598848659, + "timestampms": 1598848659201, + "type": "sell" + }, + { + "amount": "0.0000288", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371814, + "timestamp": 1598848659, + "timestampms": 1598848659177, + "type": "buy" + }, + { + "amount": "0.0002001", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371808, + "timestamp": 1598848649, + "timestampms": 1598848649038, + "type": "sell" + }, + { + "amount": "0.000275", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371803, + "timestamp": 1598848649, + "timestampms": 1598848649013, + "type": "buy" + }, + { + "amount": "0.0001743", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371795, + "timestamp": 1598848638, + "timestampms": 1598848638865, + "type": "sell" + }, + { + "amount": "0.0009966", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371790, + "timestamp": 1598848638, + "timestampms": 1598848638839, + "type": "buy" + }, + { + "amount": "0.0007403", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371781, + "timestamp": 1598848628, + "timestampms": 1598848628676, + "type": "sell" + }, + { + "amount": "0.0001988", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371776, + "timestamp": 1598848628, + "timestampms": 1598848628651, + "type": "buy" + }, + { + "amount": "0.0005233", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371537, + "timestamp": 1598848618, + "timestampms": 1598848618506, + "type": "sell" + }, + { + "amount": "0.0004101", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371532, + "timestamp": 1598848618, + "timestampms": 1598848618481, + "type": "buy" + }, + { + "amount": "0.000092", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371524, + "timestamp": 1598848608, + "timestampms": 1598848608332, + "type": "sell" + }, + { + "amount": "0.0006655", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371519, + "timestamp": 1598848608, + "timestampms": 1598848608302, + "type": "buy" + }, + { + "amount": "0.0009364", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371511, + "timestamp": 1598848598, + "timestampms": 1598848598172, + "type": "sell" + }, + { + "amount": "0.0009631", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371506, + "timestamp": 1598848598, + "timestampms": 1598848598147, + "type": "buy" + }, + { + "amount": "0.0007104", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371500, + "timestamp": 1598848588, + "timestampms": 1598848588004, + "type": "sell" + }, + { + "amount": "0.000362", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371495, + "timestamp": 1598848587, + "timestampms": 1598848587980, + "type": "buy" + }, + { + "amount": "0.0001778", + "exchange": "gemini", + "price": "11690.00", + "tid": 642371487, + "timestamp": 1598848577, + "timestampms": 1598848577840, + "type": "sell" + }, + { + "amount": "0.0005828", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371482, + "timestamp": 1598848577, + "timestampms": 1598848577817, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.89", + "tid": 642371472, + "timestamp": 1598848567, + "timestampms": 1598848567688, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371219, + "timestamp": 1598848557, + "timestampms": 1598848557549, + "type": "buy" + }, + { + "amount": "0.0006708", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371211, + "timestamp": 1598848547, + "timestampms": 1598848547421, + "type": "sell" + }, + { + "amount": "0.0007916", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371206, + "timestamp": 1598848547, + "timestampms": 1598848547398, + "type": "buy" + }, + { + "amount": "0.0007569", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371198, + "timestamp": 1598848537, + "timestampms": 1598848537260, + "type": "sell" + }, + { + "amount": "0.0007132", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371193, + "timestamp": 1598848537, + "timestampms": 1598848537231, + "type": "buy" + }, + { + "amount": "0.0008695", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371187, + "timestamp": 1598848526, + "timestampms": 1598848526955, + "type": "sell" + }, + { + "amount": "0.0002564", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371182, + "timestamp": 1598848526, + "timestampms": 1598848526931, + "type": "buy" + }, + { + "amount": "0.0002534", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371174, + "timestamp": 1598848516, + "timestampms": 1598848516799, + "type": "sell" + }, + { + "amount": "0.000248", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371169, + "timestamp": 1598848516, + "timestampms": 1598848516774, + "type": "buy" + }, + { + "amount": "0.0003681", + "exchange": "gemini", + "price": "11691.02", + "tid": 642371160, + "timestamp": 1598848506, + "timestampms": 1598848506643, + "type": "sell" + }, + { + "amount": "0.000559", + "exchange": "gemini", + "price": "11691.03", + "tid": 642371155, + "timestamp": 1598848506, + "timestampms": 1598848506619, + "type": "buy" + }, + { + "amount": "0.000298", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370910, + "timestamp": 1598848496, + "timestampms": 1598848496485, + "type": "sell" + }, + { + "amount": "0.0006147", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370905, + "timestamp": 1598848496, + "timestampms": 1598848496461, + "type": "buy" + }, + { + "amount": "0.0003912", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370897, + "timestamp": 1598848486, + "timestampms": 1598848486332, + "type": "sell" + }, + { + "amount": "0.0003537", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370892, + "timestamp": 1598848486, + "timestampms": 1598848486308, + "type": "buy" + }, + { + "amount": "0.0005441", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370884, + "timestamp": 1598848476, + "timestampms": 1598848476176, + "type": "sell" + }, + { + "amount": "0.0007024", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370879, + "timestamp": 1598848476, + "timestampms": 1598848476151, + "type": "buy" + }, + { + "amount": "0.0002039", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370873, + "timestamp": 1598848466, + "timestampms": 1598848466023, + "type": "sell" + }, + { + "amount": "0.0003968", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370871, + "timestamp": 1598848466, + "timestampms": 1598848466023, + "type": "sell" + }, + { + "amount": "0.0006368", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370866, + "timestamp": 1598848465, + "timestampms": 1598848465999, + "type": "buy" + }, + { + "amount": "0.0002646", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370855, + "timestamp": 1598848455, + "timestampms": 1598848455869, + "type": "sell" + }, + { + "amount": "0.000987", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370850, + "timestamp": 1598848455, + "timestampms": 1598848455844, + "type": "buy" + }, + { + "amount": "0.0009196", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370842, + "timestamp": 1598848445, + "timestampms": 1598848445701, + "type": "sell" + }, + { + "amount": "0.0004949", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370837, + "timestamp": 1598848445, + "timestampms": 1598848445675, + "type": "buy" + }, + { + "amount": "2", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370600, + "timestamp": 1598848437, + "timestampms": 1598848437669, + "type": "buy" + }, + { + "amount": "0.069772", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370598, + "timestamp": 1598848437, + "timestampms": 1598848437669, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370592, + "timestamp": 1598848435, + "timestampms": 1598848435544, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370584, + "timestamp": 1598848425, + "timestampms": 1598848425409, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370576, + "timestamp": 1598848415, + "timestampms": 1598848415273, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.01", + "tid": 642370570, + "timestamp": 1598848405, + "timestampms": 1598848405137, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642370561, + "timestamp": 1598848395, + "timestampms": 1598848395009, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642370553, + "timestamp": 1598848384, + "timestampms": 1598848384746, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370305, + "timestamp": 1598848374, + "timestampms": 1598848374611, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370297, + "timestamp": 1598848364, + "timestampms": 1598848364470, + "type": "sell" + }, + { + "amount": "0.0006655", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370289, + "timestamp": 1598848354, + "timestampms": 1598848354343, + "type": "sell" + }, + { + "amount": "0.0007794", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370284, + "timestamp": 1598848354, + "timestampms": 1598848354320, + "type": "buy" + }, + { + "amount": "0.0005903", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370278, + "timestamp": 1598848344, + "timestampms": 1598848344188, + "type": "sell" + }, + { + "amount": "0.0001157", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370273, + "timestamp": 1598848344, + "timestampms": 1598848344158, + "type": "buy" + }, + { + "amount": "0.0003591", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370263, + "timestamp": 1598848334, + "timestampms": 1598848334025, + "type": "sell" + }, + { + "amount": "0.0004916", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370258, + "timestamp": 1598848333, + "timestampms": 1598848333991, + "type": "buy" + }, + { + "amount": "0.0006661", + "exchange": "gemini", + "price": "11691.02", + "tid": 642370250, + "timestamp": 1598848323, + "timestampms": 1598848323857, + "type": "sell" + }, + { + "amount": "0.0004414", + "exchange": "gemini", + "price": "11691.03", + "tid": 642370245, + "timestamp": 1598848323, + "timestampms": 1598848323831, + "type": "buy" + }, + { + "amount": "0.0006503", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369998, + "timestamp": 1598848313, + "timestampms": 1598848313694, + "type": "sell" + }, + { + "amount": "0.0004874", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369993, + "timestamp": 1598848313, + "timestampms": 1598848313670, + "type": "buy" + }, + { + "amount": "0.0002995", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369985, + "timestamp": 1598848303, + "timestampms": 1598848303537, + "type": "sell" + }, + { + "amount": "0.0005772", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369980, + "timestamp": 1598848303, + "timestampms": 1598848303514, + "type": "buy" + }, + { + "amount": "0.0009411", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369972, + "timestamp": 1598848293, + "timestampms": 1598848293384, + "type": "sell" + }, + { + "amount": "0.0004638", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369967, + "timestamp": 1598848293, + "timestampms": 1598848293359, + "type": "buy" + }, + { + "amount": "0.0006568", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369961, + "timestamp": 1598848283, + "timestampms": 1598848283208, + "type": "sell" + }, + { + "amount": "0.000253", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369956, + "timestamp": 1598848283, + "timestampms": 1598848283184, + "type": "buy" + }, + { + "amount": "0.0004052", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369947, + "timestamp": 1598848273, + "timestampms": 1598848273048, + "type": "sell" + }, + { + "amount": "0.0000892", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369942, + "timestamp": 1598848273, + "timestampms": 1598848273012, + "type": "buy" + }, + { + "amount": "0.0000415", + "exchange": "gemini", + "price": "11691.02", + "tid": 642369933, + "timestamp": 1598848262, + "timestampms": 1598848262881, + "type": "sell" + }, + { + "amount": "0.0005369", + "exchange": "gemini", + "price": "11691.03", + "tid": 642369928, + "timestamp": 1598848262, + "timestampms": 1598848262857, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369681, + "timestamp": 1598848252, + "timestampms": 1598848252733, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369673, + "timestamp": 1598848242, + "timestampms": 1598848242596, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369665, + "timestamp": 1598848232, + "timestampms": 1598848232444, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.24", + "tid": 642369659, + "timestamp": 1598848222, + "timestampms": 1598848222281, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369649, + "timestamp": 1598848212, + "timestampms": 1598848212148, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.46", + "tid": 642369641, + "timestamp": 1598848201, + "timestampms": 1598848201983, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369394, + "timestamp": 1598848191, + "timestampms": 1598848191833, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369386, + "timestamp": 1598848181, + "timestampms": 1598848181694, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369378, + "timestamp": 1598848171, + "timestampms": 1598848171451, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369372, + "timestamp": 1598848161, + "timestampms": 1598848161307, + "type": "buy" + }, + { + "amount": "0.0007977", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369363, + "timestamp": 1598848151, + "timestampms": 1598848151049, + "type": "sell" + }, + { + "amount": "0.0009776", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369358, + "timestamp": 1598848151, + "timestampms": 1598848151016, + "type": "buy" + }, + { + "amount": "0.0006412", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369349, + "timestamp": 1598848140, + "timestampms": 1598848140866, + "type": "sell" + }, + { + "amount": "0.0007287", + "exchange": "gemini", + "price": "11690.84", + "tid": 642369344, + "timestamp": 1598848140, + "timestampms": 1598848140840, + "type": "buy" + }, + { + "amount": "0.0002288", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369101, + "timestamp": 1598848130, + "timestampms": 1598848130486, + "type": "sell" + }, + { + "amount": "0.0006634", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369096, + "timestamp": 1598848130, + "timestampms": 1598848130461, + "type": "buy" + }, + { + "amount": "0.0006886", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369090, + "timestamp": 1598848120, + "timestampms": 1598848120314, + "type": "sell" + }, + { + "amount": "0.000879", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369085, + "timestamp": 1598848120, + "timestampms": 1598848120289, + "type": "buy" + }, + { + "amount": "0.000585", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369077, + "timestamp": 1598848110, + "timestampms": 1598848110154, + "type": "sell" + }, + { + "amount": "0.0003618", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369072, + "timestamp": 1598848110, + "timestampms": 1598848110129, + "type": "buy" + }, + { + "amount": "0.0003633", + "exchange": "gemini", + "price": "11690.00", + "tid": 642369064, + "timestamp": 1598848099, + "timestampms": 1598848099993, + "type": "sell" + }, + { + "amount": "0.0003905", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369059, + "timestamp": 1598848099, + "timestampms": 1598848099967, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369051, + "timestamp": 1598848089, + "timestampms": 1598848089832, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.00", + "tid": 642369043, + "timestamp": 1598848079, + "timestampms": 1598848079702, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368790, + "timestamp": 1598848069, + "timestampms": 1598848069569, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368784, + "timestamp": 1598848059, + "timestampms": 1598848059279, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368776, + "timestamp": 1598848049, + "timestampms": 1598848049153, + "type": "buy" + }, + { + "amount": "0.000479", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368768, + "timestamp": 1598848038, + "timestampms": 1598848038994, + "type": "sell" + }, + { + "amount": "0.0008482", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368763, + "timestamp": 1598848038, + "timestampms": 1598848038964, + "type": "buy" + }, + { + "amount": "0.0008144", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368756, + "timestamp": 1598848028, + "timestampms": 1598848028834, + "type": "sell" + }, + { + "amount": "0.0001039", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368751, + "timestamp": 1598848028, + "timestampms": 1598848028807, + "type": "buy" + }, + { + "amount": "0.0000404", + "exchange": "gemini", + "price": "11690.00", + "tid": 642368742, + "timestamp": 1598848018, + "timestampms": 1598848018673, + "type": "sell" + }, + { + "amount": "0.0003341", + "exchange": "gemini", + "price": "11690.01", + "tid": 642368737, + "timestamp": 1598848018, + "timestampms": 1598848018647, + "type": "buy" + }, + { + "amount": "1.523391", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368568, + "timestamp": 1598848010, + "timestampms": 1598848010368, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368501, + "timestamp": 1598848008, + "timestampms": 1598848008510, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.21", + "tid": 642368495, + "timestamp": 1598847998, + "timestampms": 1598847998312, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368487, + "timestamp": 1598847988, + "timestampms": 1598847988165, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368479, + "timestamp": 1598847978, + "timestampms": 1598847978036, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368471, + "timestamp": 1598847967, + "timestampms": 1598847967889, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11690.30", + "tid": 642368463, + "timestamp": 1598847957, + "timestampms": 1598847957763, + "type": "buy" + }, + { + "amount": "0.472609", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368360, + "timestamp": 1598847953, + "timestampms": 1598847953333, + "type": "buy" + }, + { + "amount": "0.032101", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368355, + "timestamp": 1598847953, + "timestampms": 1598847953309, + "type": "buy" + }, + { + "amount": "0.063582", + "exchange": "gemini", + "price": "11690.07", + "tid": 642368350, + "timestamp": 1598847953, + "timestampms": 1598847953284, + "type": "buy" + }, + { + "amount": "0.255298", + "exchange": "gemini", + "price": "11690.22", + "tid": 642368291, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.4994", + "exchange": "gemini", + "price": "11690.23", + "tid": 642368289, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.4942", + "exchange": "gemini", + "price": "11690.24", + "tid": 642368287, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.046436", + "exchange": "gemini", + "price": "11690.25", + "tid": 642368285, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.136374", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368283, + "timestamp": 1598847949, + "timestampms": 1598847949361, + "type": "sell" + }, + { + "amount": "0.063626", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368278, + "timestamp": 1598847949, + "timestampms": 1598847949338, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368211, + "timestamp": 1598847947, + "timestampms": 1598847947611, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368205, + "timestamp": 1598847937, + "timestampms": 1598847937343, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368197, + "timestamp": 1598847927, + "timestampms": 1598847927214, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.61", + "tid": 642368189, + "timestamp": 1598847917, + "timestampms": 1598847917080, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.84", + "tid": 642368182, + "timestamp": 1598847906, + "timestampms": 1598847906946, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11693.84", + "tid": 642368173, + "timestamp": 1598847896, + "timestampms": 1598847896813, + "type": "buy" + }, + { + "amount": "0.0004696", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367924, + "timestamp": 1598847886, + "timestampms": 1598847886677, + "type": "sell" + }, + { + "amount": "0.0007677", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367919, + "timestamp": 1598847886, + "timestampms": 1598847886648, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367913, + "timestamp": 1598847876, + "timestampms": 1598847876314, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367904, + "timestamp": 1598847866, + "timestampms": 1598847866163, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367896, + "timestamp": 1598847856, + "timestampms": 1598847856039, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367887, + "timestamp": 1598847845, + "timestampms": 1598847845919, + "type": "buy" + }, + { + "amount": "0.0002559", + "exchange": "gemini", + "price": "11691.60", + "tid": 642367878, + "timestamp": 1598847835, + "timestampms": 1598847835789, + "type": "sell" + }, + { + "amount": "0.0004689", + "exchange": "gemini", + "price": "11694.43", + "tid": 642367873, + "timestamp": 1598847835, + "timestampms": 1598847835764, + "type": "buy" + }, + { + "amount": "0.03464", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367692, + "timestamp": 1598847827, + "timestampms": 1598847827147, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367626, + "timestamp": 1598847825, + "timestampms": 1598847825624, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367619, + "timestamp": 1598847815, + "timestampms": 1598847815347, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367611, + "timestamp": 1598847805, + "timestampms": 1598847805216, + "type": "sell" + }, + { + "amount": "0.0004673", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367602, + "timestamp": 1598847795, + "timestampms": 1598847795088, + "type": "sell" + }, + { + "amount": "0.0004929", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367597, + "timestamp": 1598847795, + "timestampms": 1598847795051, + "type": "buy" + }, + { + "amount": "0.0006385", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367591, + "timestamp": 1598847784, + "timestampms": 1598847784911, + "type": "sell" + }, + { + "amount": "0.000777", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367586, + "timestamp": 1598847784, + "timestampms": 1598847784886, + "type": "buy" + }, + { + "amount": "0.0004177", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367576, + "timestamp": 1598847774, + "timestampms": 1598847774753, + "type": "sell" + }, + { + "amount": "0.0000148", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367571, + "timestamp": 1598847774, + "timestampms": 1598847774728, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367329, + "timestamp": 1598847764, + "timestampms": 1598847764594, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367322, + "timestamp": 1598847754, + "timestampms": 1598847754324, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367314, + "timestamp": 1598847744, + "timestampms": 1598847744186, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367304, + "timestamp": 1598847734, + "timestampms": 1598847734045, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367298, + "timestamp": 1598847723, + "timestampms": 1598847723789, + "type": "buy" + }, + { + "amount": "0.0006687", + "exchange": "gemini", + "price": "11694.17", + "tid": 642367289, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.00001", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367287, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.00001", + "exchange": "gemini", + "price": "11696.02", + "tid": 642367285, + "timestamp": 1598847713, + "timestampms": 1598847713651, + "type": "sell" + }, + { + "amount": "0.0008684", + "exchange": "gemini", + "price": "11696.03", + "tid": 642367280, + "timestamp": 1598847713, + "timestampms": 1598847713627, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367047, + "timestamp": 1598847703, + "timestampms": 1598847703492, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367040, + "timestamp": 1598847693, + "timestampms": 1598847693251, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367032, + "timestamp": 1598847683, + "timestampms": 1598847683118, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11697.72", + "tid": 642367023, + "timestamp": 1598847672, + "timestampms": 1598847672986, + "type": "sell" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11701.08", + "tid": 642367017, + "timestamp": 1598847662, + "timestampms": 1598847662851, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11701.08", + "tid": 642367007, + "timestamp": 1598847652, + "timestampms": 1598847652694, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366749, + "timestamp": 1598847642, + "timestampms": 1598847642562, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366742, + "timestamp": 1598847632, + "timestampms": 1598847632424, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366734, + "timestamp": 1598847622, + "timestampms": 1598847622290, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366724, + "timestamp": 1598847612, + "timestampms": 1598847612156, + "type": "buy" + }, + { + "amount": "0.0008005", + "exchange": "gemini", + "price": "11699.29", + "tid": 642366718, + "timestamp": 1598847601, + "timestampms": 1598847601994, + "type": "sell" + }, + { + "amount": "0.0005064", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366713, + "timestamp": 1598847601, + "timestampms": 1598847601970, + "type": "buy" + }, + { + "amount": "0.0001031", + "exchange": "gemini", + "price": "11699.29", + "tid": 642366704, + "timestamp": 1598847591, + "timestampms": 1598847591844, + "type": "sell" + }, + { + "amount": "0.0003043", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366699, + "timestamp": 1598847591, + "timestampms": 1598847591817, + "type": "buy" + }, + { + "amount": "0.002", + "exchange": "gemini", + "price": "11699.30", + "tid": 642366451, + "timestamp": 1598847581, + "timestampms": 1598847581676, + "type": "buy" + } + ], + "queryString": "limit_trades=500\u0026since=1598847581", + "bodyParams": "", + "headers": {} + } + ] + }, "/v1/trades/btcusd": { "GET": [ { diff --git a/testdata/http_mock/localbitcoins/localbitcoins.json b/testdata/http_mock/localbitcoins/localbitcoins.json index 7ca02489..4c893e81 100644 --- a/testdata/http_mock/localbitcoins/localbitcoins.json +++ b/testdata/http_mock/localbitcoins/localbitcoins.json @@ -3395,6 +3395,3017 @@ "headers": {} } ] + }, + "/bitcoincharts/LTC/trades.json": { + "GET": [ + { + "data": [ + { + "amount": "0.00052397", + "date": 1598845944, + "price": "190.85", + "tid": 46128396 + }, + { + "amount": "0.00063115", + "date": 1598841630, + "price": "190.13", + "tid": 46127987 + }, + { + "amount": "0.00525956", + "date": 1598837666, + "price": "190.13", + "tid": 46127598 + }, + { + "amount": "0.00345134", + "date": 1598822322, + "price": "191.23", + "tid": 46124282 + }, + { + "amount": "0.00112679", + "date": 1598761827, + "price": "204.12", + "tid": 46107744 + }, + { + "amount": "0.00305976", + "date": 1598742240, + "price": "202.63", + "tid": 46103995 + }, + { + "amount": "0.00083897", + "date": 1598739007, + "price": "202.63", + "tid": 46102862 + }, + { + "amount": "0.00083399", + "date": 1598732906, + "price": "203.84", + "tid": 46100515 + }, + { + "amount": "0.00083897", + "date": 1598729130, + "price": "202.63", + "tid": 46099016 + }, + { + "amount": "0.00098203", + "date": 1598723053, + "price": "203.66", + "tid": 46095549 + }, + { + "amount": "0.00122754", + "date": 1598722254, + "price": "203.66", + "tid": 46095365 + }, + { + "amount": "0.00344387", + "date": 1598721074, + "price": "203.26", + "tid": 46093872 + }, + { + "amount": "0.00088635", + "date": 1598710102, + "price": "203.08", + "tid": 46087785 + }, + { + "amount": "0.00679167", + "date": 1598676510, + "price": "203.19", + "tid": 46078861 + }, + { + "amount": "0.00146944", + "date": 1598664447, + "price": "204.16", + "tid": 46077390 + }, + { + "amount": "0.00121077", + "date": 1598658577, + "price": "206.48", + "tid": 46075681 + }, + { + "amount": "0.00048421", + "date": 1598655635, + "price": "206.52", + "tid": 46074720 + }, + { + "amount": "0.00491102", + "date": 1598650728, + "price": "205.66", + "tid": 46072674 + }, + { + "amount": "0.01195770", + "date": 1598632962, + "price": "202.38", + "tid": 46062024 + }, + { + "amount": "0.01935770", + "date": 1598613396, + "price": "203.02", + "tid": 46051154 + }, + { + "amount": "0.00275835", + "date": 1598613157, + "price": "203.02", + "tid": 46050997 + }, + { + "amount": "0.01956249", + "date": 1598554886, + "price": "207.54", + "tid": 46035405 + }, + { + "amount": "0.00216826", + "date": 1598550980, + "price": "207.54", + "tid": 46033462 + }, + { + "amount": "0.00341642", + "date": 1598550508, + "price": "207.82", + "tid": 46033230 + }, + { + "amount": "0.00109040", + "date": 1598531056, + "price": "201.76", + "tid": 46021471 + }, + { + "amount": "0.00100361", + "date": 1598526626, + "price": "199.28", + "tid": 46019984 + }, + { + "amount": "0.01311132", + "date": 1598504721, + "price": "200.59", + "tid": 46015517 + }, + { + "amount": "0.00099711", + "date": 1598504536, + "price": "200.58", + "tid": 46015472 + }, + { + "amount": "0.00074779", + "date": 1598502494, + "price": "200.59", + "tid": 46015187 + }, + { + "amount": "0.00170026", + "date": 1598487882, + "price": "199.97", + "tid": 46012378 + }, + { + "amount": "0.00175026", + "date": 1598483579, + "price": "199.97", + "tid": 46011261 + }, + { + "amount": "0.00510077", + "date": 1598481177, + "price": "199.97", + "tid": 46010535 + }, + { + "amount": "0.00060009", + "date": 1598480524, + "price": "199.97", + "tid": 46010136 + }, + { + "amount": "0.00165488", + "date": 1598475867, + "price": "199.41", + "tid": 46008112 + }, + { + "amount": "0.01128329", + "date": 1598475088, + "price": "199.41", + "tid": 46008017 + }, + { + "amount": "0.00170503", + "date": 1598474953, + "price": "199.41", + "tid": 46007986 + }, + { + "amount": "0.05137294", + "date": 1598472980, + "price": "200.30", + "tid": 46007262 + }, + { + "amount": "0.00100417", + "date": 1598468514, + "price": "199.17", + "tid": 46004552 + }, + { + "amount": "0.00271125", + "date": 1598466612, + "price": "199.17", + "tid": 46003683 + }, + { + "amount": "0.00306102", + "date": 1598462048, + "price": "199.28", + "tid": 46000738 + }, + { + "amount": "0.00089829", + "date": 1598422897, + "price": "200.38", + "tid": 45985755 + }, + { + "amount": "0.00451785", + "date": 1598413473, + "price": "199.21", + "tid": 45984623 + }, + { + "amount": "0.00140852", + "date": 1598405537, + "price": "198.79", + "tid": 45983428 + }, + { + "amount": "0.00141672", + "date": 1598402904, + "price": "197.64", + "tid": 45982866 + }, + { + "amount": "0.00383819", + "date": 1598391934, + "price": "198.01", + "tid": 45979111 + }, + { + "amount": "0.00582885", + "date": 1598383105, + "price": "199.01", + "tid": 45974893 + }, + { + "amount": "0.00133402", + "date": 1598364684, + "price": "194.90", + "tid": 45962943 + }, + { + "amount": "0.00133149", + "date": 1598360109, + "price": "187.76", + "tid": 45961219 + }, + { + "amount": "0.00051398", + "date": 1598357907, + "price": "194.56", + "tid": 45960457 + }, + { + "amount": "0.02927154", + "date": 1598352392, + "price": "195.07", + "tid": 45958772 + }, + { + "amount": "0.00153799", + "date": 1598351302, + "price": "195.06", + "tid": 45958455 + }, + { + "amount": "0.00051088", + "date": 1598346253, + "price": "195.74", + "tid": 45956834 + }, + { + "amount": "0.00087701", + "date": 1598323062, + "price": "193.84", + "tid": 45953501 + }, + { + "amount": "0.00383837", + "date": 1598314449, + "price": "192.79", + "tid": 45951328 + }, + { + "amount": "0.00238564", + "date": 1598297382, + "price": "192.82", + "tid": 45942969 + }, + { + "amount": "0.00774348", + "date": 1598296397, + "price": "192.42", + "tid": 45942256 + }, + { + "amount": "0.00612245", + "date": 1598292882, + "price": "191.10", + "tid": 45940165 + }, + { + "amount": "0.00130520", + "date": 1598291565, + "price": "183.88", + "tid": 45939547 + }, + { + "amount": "0.00082919", + "date": 1598275570, + "price": "192.96", + "tid": 45930195 + }, + { + "amount": "0.01048633", + "date": 1598256310, + "price": "186.91", + "tid": 45924509 + }, + { + "amount": "0.00056541", + "date": 1598251749, + "price": "194.55", + "tid": 45923910 + }, + { + "amount": "0.05475223", + "date": 1598224842, + "price": "194.33", + "tid": 45920589 + }, + { + "amount": "0.00592722", + "date": 1598215892, + "price": "194.02", + "tid": 45918022 + }, + { + "amount": "0.00052198", + "date": 1598203782, + "price": "191.58", + "tid": 45913783 + }, + { + "amount": "0.00057087", + "date": 1598202077, + "price": "192.69", + "tid": 45913774 + }, + { + "amount": "0.00062581", + "date": 1598201376, + "price": "191.75", + "tid": 45913678 + }, + { + "amount": "0.00124465", + "date": 1598195099, + "price": "200.86", + "tid": 45910835 + }, + { + "amount": "0.00059746", + "date": 1598193137, + "price": "200.85", + "tid": 45910081 + }, + { + "amount": "0.00061862", + "date": 1598189871, + "price": "193.98", + "tid": 45908945 + }, + { + "amount": "0.00061897", + "date": 1598189890, + "price": "193.87", + "tid": 45908936 + }, + { + "amount": "0.00056707", + "date": 1598188731, + "price": "193.98", + "tid": 45908641 + }, + { + "amount": "0.00051403", + "date": 1598188710, + "price": "194.54", + "tid": 45908637 + }, + { + "amount": "0.00169213", + "date": 1598188660, + "price": "200.93", + "tid": 45908534 + }, + { + "amount": "0.00049741", + "date": 1598185211, + "price": "201.04", + "tid": 45907644 + }, + { + "amount": "0.00049278", + "date": 1598152822, + "price": "202.93", + "tid": 45902511 + }, + { + "amount": "0.00101549", + "date": 1598144293, + "price": "196.95", + "tid": 45901047 + }, + { + "amount": "0.00409795", + "date": 1598123955, + "price": "197.66", + "tid": 45894245 + }, + { + "amount": "0.00505817", + "date": 1598116655, + "price": "197.70", + "tid": 45890851 + }, + { + "amount": "0.00080675", + "date": 1598111635, + "price": "136.35", + "tid": 45888000 + }, + { + "amount": "0.00073341", + "date": 1598112086, + "price": "136.35", + "tid": 45887995 + }, + { + "amount": "0.01436520", + "date": 1598110577, + "price": "197.70", + "tid": 45887627 + }, + { + "amount": "0.00095343", + "date": 1598110659, + "price": "136.35", + "tid": 45887425 + }, + { + "amount": "0.00073341", + "date": 1598110636, + "price": "136.35", + "tid": 45887387 + }, + { + "amount": "0.00246628", + "date": 1598110313, + "price": "198.68", + "tid": 45887316 + }, + { + "amount": "0.00062883", + "date": 1598110741, + "price": "190.83", + "tid": 45887084 + }, + { + "amount": "0.00080675", + "date": 1598109617, + "price": "136.35", + "tid": 45886799 + }, + { + "amount": "0.00062762", + "date": 1598106546, + "price": "191.20", + "tid": 45885036 + }, + { + "amount": "0.00110783", + "date": 1598104409, + "price": "135.40", + "tid": 45884103 + }, + { + "amount": "0.00243358", + "date": 1598104539, + "price": "197.24", + "tid": 45883937 + }, + { + "amount": "0.00057712", + "date": 1598103600, + "price": "190.60", + "tid": 45883733 + }, + { + "amount": "0.00073855", + "date": 1598103737, + "price": "135.40", + "tid": 45883719 + }, + { + "amount": "0.00050485", + "date": 1598100497, + "price": "198.08", + "tid": 45882543 + }, + { + "amount": "0.00050241", + "date": 1598097736, + "price": "199.04", + "tid": 45881626 + }, + { + "amount": "0.01307619", + "date": 1598091010, + "price": "198.07", + "tid": 45879706 + }, + { + "amount": "0.00337226", + "date": 1598065701, + "price": "198.68", + "tid": 45875652 + }, + { + "amount": "0.00055823", + "date": 1598047243, + "price": "197.05", + "tid": 45870781 + }, + { + "amount": "0.01469470", + "date": 1598038961, + "price": "197.35", + "tid": 45866701 + }, + { + "amount": "0.00668862", + "date": 1598037246, + "price": "197.35", + "tid": 45865813 + }, + { + "amount": "0.00120998", + "date": 1598035594, + "price": "198.35", + "tid": 45865236 + }, + { + "amount": "0.00101435", + "date": 1598031013, + "price": "197.17", + "tid": 45862489 + }, + { + "amount": "0.00432900", + "date": 1598030113, + "price": "196.35", + "tid": 45861444 + }, + { + "amount": "0.00310670", + "date": 1598029524, + "price": "196.35", + "tid": 45861337 + }, + { + "amount": "0.00051065", + "date": 1598020711, + "price": "195.83", + "tid": 45855897 + }, + { + "amount": "0.00082106", + "date": 1598020439, + "price": "194.87", + "tid": 45855714 + }, + { + "amount": "0.00298339", + "date": 1598017502, + "price": "194.41", + "tid": 45854037 + }, + { + "amount": "0.00102807", + "date": 1598007991, + "price": "194.54", + "tid": 45849712 + }, + { + "amount": "0.04268420", + "date": 1597971431, + "price": "191.64", + "tid": 45842047 + }, + { + "amount": "0.00279851", + "date": 1597968855, + "price": "192.96", + "tid": 45841367 + }, + { + "amount": "0.00067190", + "date": 1597946665, + "price": "193.48", + "tid": 45831454 + }, + { + "amount": "0.00083338", + "date": 1597929752, + "price": "191.99", + "tid": 45821337 + }, + { + "amount": "0.00201908", + "date": 1597927945, + "price": "198.11", + "tid": 45820234 + }, + { + "amount": "0.00051520", + "date": 1597926141, + "price": "194.10", + "tid": 45819806 + }, + { + "amount": "0.00051578", + "date": 1597917852, + "price": "193.88", + "tid": 45817138 + }, + { + "amount": "0.00089010", + "date": 1597898301, + "price": "190.99", + "tid": 45813473 + }, + { + "amount": "0.00054445", + "date": 1597892518, + "price": "183.67", + "tid": 45812789 + }, + { + "amount": "0.03432322", + "date": 1597885623, + "price": "185.88", + "tid": 45811148 + }, + { + "amount": "0.00169274", + "date": 1597878388, + "price": "194.95", + "tid": 45809333 + }, + { + "amount": "0.01066667", + "date": 1597877093, + "price": "187.50", + "tid": 45808483 + }, + { + "amount": "0.01447072", + "date": 1597866314, + "price": "190.73", + "tid": 45804065 + }, + { + "amount": "0.01192853", + "date": 1597863915, + "price": "190.30", + "tid": 45802246 + }, + { + "amount": "0.00143332", + "date": 1597862329, + "price": "195.35", + "tid": 45801290 + }, + { + "amount": "0.00317091", + "date": 1597862501, + "price": "189.22", + "tid": 45801220 + }, + { + "amount": "0.01189092", + "date": 1597860462, + "price": "189.22", + "tid": 45800369 + }, + { + "amount": "0.00107170", + "date": 1597859423, + "price": "195.95", + "tid": 45799834 + }, + { + "amount": "0.00727584", + "date": 1597852675, + "price": "186.92", + "tid": 45795494 + }, + { + "amount": "0.00312272", + "date": 1597844903, + "price": "192.14", + "tid": 45790665 + }, + { + "amount": "0.00120148", + "date": 1597841063, + "price": "191.43", + "tid": 45789233 + }, + { + "amount": "0.00105247", + "date": 1597824875, + "price": "190.03", + "tid": 45784538 + }, + { + "amount": "0.00408274", + "date": 1597802176, + "price": "183.70", + "tid": 45781320 + }, + { + "amount": "0.01103825", + "date": 1597792071, + "price": "183.00", + "tid": 45777549 + }, + { + "amount": "0.00092896", + "date": 1597790372, + "price": "183.00", + "tid": 45777232 + }, + { + "amount": "0.00252456", + "date": 1597787510, + "price": "182.21", + "tid": 45776210 + }, + { + "amount": "0.00189210", + "date": 1597766060, + "price": "184.98", + "tid": 45763779 + }, + { + "amount": "0.00132478", + "date": 1597758122, + "price": "188.71", + "tid": 45758820 + }, + { + "amount": "0.00149214", + "date": 1597749997, + "price": "187.65", + "tid": 45755467 + }, + { + "amount": "0.00053591", + "date": 1597747337, + "price": "186.60", + "tid": 45754816 + }, + { + "amount": "0.00053245", + "date": 1597734636, + "price": "187.81", + "tid": 45751721 + }, + { + "amount": "0.00148344", + "date": 1597731493, + "price": "188.75", + "tid": 45751154 + }, + { + "amount": "0.00866710", + "date": 1597723079, + "price": "185.76", + "tid": 45750110 + }, + { + "amount": "0.00075366", + "date": 1597721290, + "price": "185.76", + "tid": 45749872 + }, + { + "amount": "0.01196237", + "date": 1597705440, + "price": "183.91", + "tid": 45746017 + }, + { + "amount": "0.00218830", + "date": 1597693580, + "price": "187.36", + "tid": 45740579 + }, + { + "amount": "0.00494517", + "date": 1597692351, + "price": "186.04", + "tid": 45739390 + }, + { + "amount": "0.00871507", + "date": 1597687152, + "price": "183.59", + "tid": 45736158 + }, + { + "amount": "0.01103173", + "date": 1597685670, + "price": "190.36", + "tid": 45735466 + }, + { + "amount": "0.00313077", + "date": 1597681626, + "price": "194.84", + "tid": 45732647 + }, + { + "amount": "0.00056792", + "date": 1597678949, + "price": "193.69", + "tid": 45730946 + }, + { + "amount": "0.00172992", + "date": 1597674458, + "price": "190.76", + "tid": 45727719 + }, + { + "amount": "0.00052927", + "date": 1597659738, + "price": "188.94", + "tid": 45722603 + }, + { + "amount": "0.01648939", + "date": 1597612764, + "price": "196.49", + "tid": 45714736 + }, + { + "amount": "0.00496367", + "date": 1597608721, + "price": "195.42", + "tid": 45713667 + }, + { + "amount": "0.00081745", + "date": 1597606218, + "price": "195.73", + "tid": 45712784 + }, + { + "amount": "0.00930425", + "date": 1597604433, + "price": "193.46", + "tid": 45711721 + }, + { + "amount": "0.00092946", + "date": 1597599544, + "price": "193.66", + "tid": 45710090 + }, + { + "amount": "0.00051422", + "date": 1597596379, + "price": "194.47", + "tid": 45708981 + }, + { + "amount": "0.00082039", + "date": 1597594452, + "price": "195.03", + "tid": 45707778 + }, + { + "amount": "0.00086988", + "date": 1597592785, + "price": "195.43", + "tid": 45707221 + }, + { + "amount": "0.00597317", + "date": 1597584040, + "price": "197.55", + "tid": 45703506 + }, + { + "amount": "0.01534684", + "date": 1597574284, + "price": "195.48", + "tid": 45700940 + }, + { + "amount": "0.00051049", + "date": 1597563377, + "price": "195.89", + "tid": 45698739 + }, + { + "amount": "0.00051343", + "date": 1597545512, + "price": "194.77", + "tid": 45696675 + }, + { + "amount": "0.00126243", + "date": 1597541798, + "price": "198.03", + "tid": 45696116 + }, + { + "amount": "0.00066425", + "date": 1597537958, + "price": "195.71", + "tid": 45695205 + }, + { + "amount": "0.00239354", + "date": 1597524023, + "price": "200.54", + "tid": 45690365 + }, + { + "amount": "0.03961585", + "date": 1597522558, + "price": "199.92", + "tid": 45689827 + }, + { + "amount": "0.00946904", + "date": 1597519466, + "price": "201.71", + "tid": 45688166 + }, + { + "amount": "0.00268577", + "date": 1597512002, + "price": "201.06", + "tid": 45684204 + }, + { + "amount": "0.00252826", + "date": 1597497797, + "price": "209.63", + "tid": 45675651 + }, + { + "amount": "0.00047279", + "date": 1597491736, + "price": "211.51", + "tid": 45673557 + }, + { + "amount": "0.00155947", + "date": 1597480151, + "price": "211.61", + "tid": 45670308 + }, + { + "amount": "0.00741987", + "date": 1597470836, + "price": "202.16", + "tid": 45668635 + }, + { + "amount": "0.00198488", + "date": 1597470143, + "price": "211.60", + "tid": 45668527 + }, + { + "amount": "0.00490388", + "date": 1597470053, + "price": "203.92", + "tid": 45668523 + }, + { + "amount": "0.00987313", + "date": 1597470201, + "price": "202.57", + "tid": 45668482 + }, + { + "amount": "0.00118226", + "date": 1597444490, + "price": "211.46", + "tid": 45662886 + }, + { + "amount": "0.01676960", + "date": 1597444775, + "price": "210.50", + "tid": 45662863 + }, + { + "amount": "0.00231722", + "date": 1597442640, + "price": "211.46", + "tid": 45661754 + }, + { + "amount": "0.01040386", + "date": 1597440711, + "price": "211.46", + "tid": 45661164 + }, + { + "amount": "0.00203637", + "date": 1597440496, + "price": "211.16", + "tid": 45660780 + }, + { + "amount": "0.01477323", + "date": 1597439081, + "price": "203.07", + "tid": 45660308 + }, + { + "amount": "0.01023350", + "date": 1597436272, + "price": "208.14", + "tid": 45658692 + }, + { + "amount": "0.00147654", + "date": 1597431375, + "price": "209.95", + "tid": 45656166 + }, + { + "amount": "0.00081309", + "date": 1597431004, + "price": "209.08", + "tid": 45655828 + }, + { + "amount": "0.00172068", + "date": 1597429448, + "price": "209.22", + "tid": 45654726 + }, + { + "amount": "0.00113830", + "date": 1597419865, + "price": "210.84", + "tid": 45647988 + }, + { + "amount": "0.00476440", + "date": 1597409359, + "price": "209.89", + "tid": 45641492 + }, + { + "amount": "0.00094197", + "date": 1597406771, + "price": "212.32", + "tid": 45640497 + }, + { + "amount": "0.00049000", + "date": 1597406550, + "price": "204.08", + "tid": 45640465 + }, + { + "amount": "0.00046871", + "date": 1597403534, + "price": "213.35", + "tid": 45639376 + }, + { + "amount": "0.00047188", + "date": 1597396480, + "price": "211.92", + "tid": 45637426 + }, + { + "amount": "0.00056630", + "date": 1597380144, + "price": "211.90", + "tid": 45634109 + }, + { + "amount": "0.02154806", + "date": 1597374913, + "price": "211.62", + "tid": 45633471 + }, + { + "amount": "0.00623760", + "date": 1597374595, + "price": "211.62", + "tid": 45633409 + }, + { + "amount": "0.00950119", + "date": 1597373462, + "price": "210.50", + "tid": 45633187 + }, + { + "amount": "0.01867871", + "date": 1597364780, + "price": "210.40", + "tid": 45631234 + }, + { + "amount": "0.00385678", + "date": 1597362858, + "price": "210.02", + "tid": 45630691 + }, + { + "amount": "0.00765400", + "date": 1597350070, + "price": "216.88", + "tid": 45625328 + }, + { + "amount": "0.00083045", + "date": 1597345810, + "price": "216.75", + "tid": 45622967 + }, + { + "amount": "0.04624438", + "date": 1597342564, + "price": "215.81", + "tid": 45621219 + }, + { + "amount": "0.00170806", + "date": 1597324614, + "price": "216.62", + "tid": 45610105 + }, + { + "amount": "0.00045496", + "date": 1597312702, + "price": "219.80", + "tid": 45605694 + }, + { + "amount": "0.00045506", + "date": 1597308735, + "price": "219.75", + "tid": 45604761 + }, + { + "amount": "0.00316137", + "date": 1597306299, + "price": "208.77", + "tid": 45604097 + }, + { + "amount": "0.00304512", + "date": 1597306222, + "price": "216.74", + "tid": 45603947 + }, + { + "amount": "0.00506576", + "date": 1597295367, + "price": "215.17", + "tid": 45602439 + }, + { + "amount": "0.00417053", + "date": 1597291670, + "price": "215.80", + "tid": 45602038 + }, + { + "amount": "0.00411843", + "date": 1597289170, + "price": "218.53", + "tid": 45601734 + }, + { + "amount": "0.00279499", + "date": 1597268198, + "price": "214.67", + "tid": 45595400 + }, + { + "amount": "0.00621524", + "date": 1597250720, + "price": "213.99", + "tid": 45585519 + }, + { + "amount": "0.00046637", + "date": 1597239179, + "price": "214.42", + "tid": 45578230 + }, + { + "amount": "0.00070021", + "date": 1597198058, + "price": "214.22", + "tid": 45569003 + }, + { + "amount": "0.00284223", + "date": 1597191548, + "price": "214.62", + "tid": 45567431 + }, + { + "amount": "0.00663272", + "date": 1597186899, + "price": "214.09", + "tid": 45565792 + }, + { + "amount": "0.00115290", + "date": 1597180838, + "price": "208.17", + "tid": 45563418 + }, + { + "amount": "0.00228811", + "date": 1597172564, + "price": "209.78", + "tid": 45558772 + }, + { + "amount": "0.00048828", + "date": 1597165039, + "price": "204.80", + "tid": 45554891 + }, + { + "amount": "0.03370787", + "date": 1597160107, + "price": "201.14", + "tid": 45551231 + }, + { + "amount": "0.00474518", + "date": 1597155791, + "price": "210.74", + "tid": 45548683 + }, + { + "amount": "0.01219512", + "date": 1597150599, + "price": "207.46", + "tid": 45546231 + }, + { + "amount": "0.00097177", + "date": 1597113035, + "price": "205.81", + "tid": 45538457 + }, + { + "amount": "0.01442354", + "date": 1597111088, + "price": "207.30", + "tid": 45537923 + }, + { + "amount": "0.00404644", + "date": 1597107731, + "price": "207.59", + "tid": 45537230 + }, + { + "amount": "0.00520521", + "date": 1597094458, + "price": "199.80", + "tid": 45531500 + }, + { + "amount": "0.00140866", + "date": 1597092640, + "price": "205.87", + "tid": 45530686 + }, + { + "amount": "0.00329346", + "date": 1597091218, + "price": "206.47", + "tid": 45529806 + }, + { + "amount": "0.00247009", + "date": 1597088172, + "price": "206.47", + "tid": 45528192 + }, + { + "amount": "0.00668409", + "date": 1597086946, + "price": "198.98", + "tid": 45526982 + }, + { + "amount": "0.00119281", + "date": 1597074779, + "price": "209.59", + "tid": 45519494 + }, + { + "amount": "0.00607557", + "date": 1597074476, + "price": "202.45", + "tid": 45518965 + }, + { + "amount": "0.00052526", + "date": 1597072735, + "price": "209.42", + "tid": 45517853 + }, + { + "amount": "0.00048121", + "date": 1596998724, + "price": "207.81", + "tid": 45498950 + }, + { + "amount": "0.00197648", + "date": 1596993895, + "price": "207.44", + "tid": 45496950 + }, + { + "amount": "0.00086393", + "date": 1596985948, + "price": "208.35", + "tid": 45493595 + }, + { + "amount": "0.00920186", + "date": 1596985039, + "price": "206.48", + "tid": 45493105 + }, + { + "amount": "0.00629601", + "date": 1596984164, + "price": "206.48", + "tid": 45492852 + }, + { + "amount": "0.01200884", + "date": 1596963647, + "price": "199.02", + "tid": 45487614 + }, + { + "amount": "0.00097059", + "date": 1596945372, + "price": "206.06", + "tid": 45485307 + }, + { + "amount": "0.00189855", + "date": 1596938177, + "price": "205.42", + "tid": 45484427 + }, + { + "amount": "0.00587807", + "date": 1596915685, + "price": "205.85", + "tid": 45477272 + }, + { + "amount": "0.00121330", + "date": 1596908811, + "price": "206.05", + "tid": 45474003 + }, + { + "amount": "0.00275629", + "date": 1596890956, + "price": "206.80", + "tid": 45463942 + }, + { + "amount": "0.00082205", + "date": 1596889102, + "price": "206.80", + "tid": 45463400 + }, + { + "amount": "0.00625188", + "date": 1596864530, + "price": "199.94", + "tid": 45457863 + }, + { + "amount": "0.02944153", + "date": 1596851219, + "price": "207.53", + "tid": 45456205 + }, + { + "amount": "0.00923541", + "date": 1596840883, + "price": "205.73", + "tid": 45452967 + }, + { + "amount": "0.00301205", + "date": 1596833079, + "price": "205.84", + "tid": 45449093 + }, + { + "amount": "0.00571595", + "date": 1596827498, + "price": "206.44", + "tid": 45445598 + }, + { + "amount": "0.00148559", + "date": 1596820928, + "price": "201.94", + "tid": 45441884 + }, + { + "amount": "0.00054827", + "date": 1596804735, + "price": "200.63", + "tid": 45431733 + }, + { + "amount": "0.00084835", + "date": 1596803180, + "price": "200.39", + "tid": 45430908 + }, + { + "amount": "0.00055152", + "date": 1596793708, + "price": "199.45", + "tid": 45427807 + }, + { + "amount": "0.02391541", + "date": 1596778582, + "price": "202.38", + "tid": 45424567 + }, + { + "amount": "0.00509548", + "date": 1596766243, + "price": "194.29", + "tid": 45422584 + }, + { + "amount": "0.00982801", + "date": 1596761549, + "price": "203.50", + "tid": 45421482 + }, + { + "amount": "0.01500552", + "date": 1596740922, + "price": "199.26", + "tid": 45411407 + }, + { + "amount": "0.00162506", + "date": 1596727073, + "price": "203.07", + "tid": 45402795 + }, + { + "amount": "0.00054009", + "date": 1596723275, + "price": "203.67", + "tid": 45400177 + }, + { + "amount": "0.00054009", + "date": 1596722666, + "price": "203.67", + "tid": 45399977 + }, + { + "amount": "0.00267718", + "date": 1596716487, + "price": "205.44", + "tid": 45396911 + }, + { + "amount": "0.00137633", + "date": 1596686442, + "price": "203.44", + "tid": 45390233 + }, + { + "amount": "0.00049155", + "date": 1596681491, + "price": "203.44", + "tid": 45389544 + }, + { + "amount": "0.00098722", + "date": 1596675192, + "price": "202.59", + "tid": 45387960 + }, + { + "amount": "0.00049215", + "date": 1596673450, + "price": "203.19", + "tid": 45387510 + }, + { + "amount": "0.00049478", + "date": 1596645835, + "price": "202.11", + "tid": 45371874 + }, + { + "amount": "0.00298070", + "date": 1596618261, + "price": "197.94", + "tid": 45359406 + }, + { + "amount": "0.00050138", + "date": 1596601220, + "price": "199.45", + "tid": 45356417 + }, + { + "amount": "0.06778977", + "date": 1596595278, + "price": "198.26", + "tid": 45355658 + }, + { + "amount": "0.00332594", + "date": 1596590429, + "price": "198.44", + "tid": 45354575 + }, + { + "amount": "0.04085150", + "date": 1596557664, + "price": "197.30", + "tid": 45337014 + }, + { + "amount": "0.00354072", + "date": 1596551298, + "price": "197.70", + "tid": 45333833 + }, + { + "amount": "0.02074059", + "date": 1596549337, + "price": "197.68", + "tid": 45332776 + }, + { + "amount": "0.00354108", + "date": 1596548586, + "price": "197.68", + "tid": 45332293 + }, + { + "amount": "0.00101569", + "date": 1596499945, + "price": "196.91", + "tid": 45320337 + }, + { + "amount": "0.01042844", + "date": 1596485020, + "price": "194.66", + "tid": 45313437 + }, + { + "amount": "0.00703791", + "date": 1596484240, + "price": "194.66", + "tid": 45312814 + }, + { + "amount": "0.00568091", + "date": 1596481057, + "price": "188.35", + "tid": 45310634 + }, + { + "amount": "0.01023332", + "date": 1596466975, + "price": "195.44", + "tid": 45300559 + }, + { + "amount": "0.00122499", + "date": 1596466394, + "price": "195.92", + "tid": 45300243 + }, + { + "amount": "0.00050375", + "date": 1596451211, + "price": "198.51", + "tid": 45293889 + }, + { + "amount": "0.00131652", + "date": 1596423520, + "price": "197.49", + "tid": 45289361 + }, + { + "amount": "0.00318118", + "date": 1596417667, + "price": "198.04", + "tid": 45288681 + }, + { + "amount": "0.01002414", + "date": 1596402620, + "price": "190.54", + "tid": 45285329 + }, + { + "amount": "0.00303582", + "date": 1596399987, + "price": "197.64", + "tid": 45284517 + }, + { + "amount": "0.00707929", + "date": 1596398709, + "price": "197.76", + "tid": 45283970 + }, + { + "amount": "0.00281464", + "date": 1596381191, + "price": "198.96", + "tid": 45276577 + }, + { + "amount": "0.00049980", + "date": 1596372985, + "price": "200.08", + "tid": 45273549 + }, + { + "amount": "0.00286856", + "date": 1596321390, + "price": "195.22", + "tid": 45262618 + }, + { + "amount": "0.00204803", + "date": 1596310690, + "price": "195.31", + "tid": 45257977 + }, + { + "amount": "0.00254505", + "date": 1596309990, + "price": "196.46", + "tid": 45257642 + }, + { + "amount": "0.00508053", + "date": 1596302910, + "price": "196.83", + "tid": 45253522 + }, + { + "amount": "0.00333165", + "date": 1596300696, + "price": "198.10", + "tid": 45252457 + }, + { + "amount": "0.00501479", + "date": 1596297656, + "price": "199.41", + "tid": 45250042 + }, + { + "amount": "0.00250777", + "date": 1596296615, + "price": "199.38", + "tid": 45249476 + }, + { + "amount": "0.00215712", + "date": 1596296023, + "price": "199.34", + "tid": 45249181 + }, + { + "amount": "0.00135556", + "date": 1596294913, + "price": "199.18", + "tid": 45248025 + }, + { + "amount": "0.00481879", + "date": 1596293175, + "price": "199.22", + "tid": 45247171 + }, + { + "amount": "0.00151141", + "date": 1596289940, + "price": "198.49", + "tid": 45245115 + }, + { + "amount": "0.00252411", + "date": 1596285457, + "price": "198.09", + "tid": 45243578 + }, + { + "amount": "0.00100432", + "date": 1596277463, + "price": "199.14", + "tid": 45242035 + }, + { + "amount": "0.00226586", + "date": 1596264491, + "price": "198.60", + "tid": 45239855 + }, + { + "amount": "0.00086015", + "date": 1596249284, + "price": "197.64", + "tid": 45237764 + }, + { + "amount": "0.00136240", + "date": 1596232650, + "price": "198.18", + "tid": 45232280 + }, + { + "amount": "0.01749404", + "date": 1596223145, + "price": "197.21", + "tid": 45226857 + }, + { + "amount": "0.00761963", + "date": 1596219413, + "price": "196.86", + "tid": 45224402 + }, + { + "amount": "0.00895432", + "date": 1596211831, + "price": "197.67", + "tid": 45218997 + }, + { + "amount": "0.00510334", + "date": 1596208659, + "price": "195.95", + "tid": 45216704 + }, + { + "amount": "0.00304847", + "date": 1596208375, + "price": "196.82", + "tid": 45216274 + }, + { + "amount": "0.00147283", + "date": 1596207316, + "price": "196.90", + "tid": 45215936 + }, + { + "amount": "0.00222988", + "date": 1596202939, + "price": "197.32", + "tid": 45212861 + }, + { + "amount": "0.00095473", + "date": 1596202277, + "price": "199.01", + "tid": 45212510 + }, + { + "amount": "0.00366356", + "date": 1596197069, + "price": "199.26", + "tid": 45210334 + }, + { + "amount": "0.00050777", + "date": 1596151768, + "price": "196.94", + "tid": 45199387 + }, + { + "amount": "0.00507434", + "date": 1596149544, + "price": "197.07", + "tid": 45198612 + }, + { + "amount": "0.00520888", + "date": 1596142404, + "price": "191.98", + "tid": 45195382 + }, + { + "amount": "0.00452102", + "date": 1596135265, + "price": "199.07", + "tid": 45192085 + }, + { + "amount": "0.03659214", + "date": 1596134184, + "price": "198.13", + "tid": 45190983 + }, + { + "amount": "0.00183580", + "date": 1596120639, + "price": "196.10", + "tid": 45182860 + }, + { + "amount": "0.00048955", + "date": 1596086054, + "price": "204.27", + "tid": 45172233 + }, + { + "amount": "0.00131797", + "date": 1596067811, + "price": "204.86", + "tid": 45168535 + }, + { + "amount": "0.00063322", + "date": 1596053774, + "price": "205.30", + "tid": 45162797 + }, + { + "amount": "0.00165611", + "date": 1596052704, + "price": "205.30", + "tid": 45162333 + }, + { + "amount": "0.01319003", + "date": 1596052123, + "price": "204.70", + "tid": 45161960 + }, + { + "amount": "0.00161409", + "date": 1596038652, + "price": "204.45", + "tid": 45153789 + }, + { + "amount": "0.00261767", + "date": 1596030850, + "price": "202.47", + "tid": 45148761 + }, + { + "amount": "0.00110143", + "date": 1595991503, + "price": "199.74", + "tid": 45138809 + }, + { + "amount": "0.00160417", + "date": 1595973134, + "price": "199.48", + "tid": 45133620 + }, + { + "amount": "0.00601583", + "date": 1595968243, + "price": "189.50", + "tid": 45131384 + }, + { + "amount": "0.00526122", + "date": 1595967275, + "price": "190.07", + "tid": 45130687 + }, + { + "amount": "0.00242884", + "date": 1595946519, + "price": "205.86", + "tid": 45118468 + }, + { + "amount": "0.00339469", + "date": 1595945169, + "price": "209.15", + "tid": 45117489 + }, + { + "amount": "0.00052887", + "date": 1595934506, + "price": "207.99", + "tid": 45113388 + }, + { + "amount": "0.00048163", + "date": 1595908965, + "price": "207.63", + "tid": 45107904 + }, + { + "amount": "0.00123551", + "date": 1595901923, + "price": "210.44", + "tid": 45106792 + }, + { + "amount": "0.00275862", + "date": 1595885670, + "price": "203.00", + "tid": 45100767 + }, + { + "amount": "0.00721326", + "date": 1595873323, + "price": "223.20", + "tid": 45092783 + }, + { + "amount": "0.00318211", + "date": 1595866871, + "price": "219.98", + "tid": 45088729 + }, + { + "amount": "0.00200027", + "date": 1595865943, + "price": "219.97", + "tid": 45088372 + }, + { + "amount": "0.00101565", + "date": 1595860947, + "price": "216.61", + "tid": 45084821 + }, + { + "amount": "0.00050783", + "date": 1595860417, + "price": "216.61", + "tid": 45084477 + }, + { + "amount": "0.00118985", + "date": 1595813457, + "price": "210.11", + "tid": 45073343 + }, + { + "amount": "0.00912540", + "date": 1595782552, + "price": "208.21", + "tid": 45063889 + }, + { + "amount": "0.00911184", + "date": 1595782726, + "price": "208.52", + "tid": 45063879 + }, + { + "amount": "0.01343913", + "date": 1595781787, + "price": "201.65", + "tid": 45063731 + }, + { + "amount": "0.00082866", + "date": 1595760500, + "price": "205.15", + "tid": 45056175 + }, + { + "amount": "0.00402564", + "date": 1595724022, + "price": "201.21", + "tid": 45050307 + }, + { + "amount": "0.00109116", + "date": 1595713339, + "price": "201.62", + "tid": 45047110 + }, + { + "amount": "0.02261442", + "date": 1595706010, + "price": "203.41", + "tid": 45044140 + }, + { + "amount": "0.00378509", + "date": 1595697973, + "price": "203.43", + "tid": 45040132 + }, + { + "amount": "0.00584710", + "date": 1595692467, + "price": "205.23", + "tid": 45036835 + }, + { + "amount": "0.00095265", + "date": 1595649376, + "price": "209.94", + "tid": 45024614 + }, + { + "amount": "0.00057159", + "date": 1595646987, + "price": "209.94", + "tid": 45024327 + }, + { + "amount": "0.00109659", + "date": 1595627727, + "price": "218.86", + "tid": 45018698 + }, + { + "amount": "0.00127592", + "date": 1595600777, + "price": "219.45", + "tid": 45002782 + }, + { + "amount": "0.00229040", + "date": 1595557877, + "price": "209.57", + "tid": 44990691 + }, + { + "amount": "0.00064241", + "date": 1595550471, + "price": "217.93", + "tid": 44988854 + }, + { + "amount": "0.01140088", + "date": 1595543785, + "price": "216.65", + "tid": 44986610 + }, + { + "amount": "0.00221228", + "date": 1595534024, + "price": "207.93", + "tid": 44980892 + }, + { + "amount": "0.00465658", + "date": 1595518725, + "price": "214.75", + "tid": 44970919 + }, + { + "amount": "0.00483047", + "date": 1595514357, + "price": "215.30", + "tid": 44968643 + }, + { + "amount": "0.01258958", + "date": 1595475003, + "price": "206.52", + "tid": 44959620 + }, + { + "amount": "0.01002072", + "date": 1595471519, + "price": "207.57", + "tid": 44959210 + }, + { + "amount": "0.00257587", + "date": 1595465654, + "price": "213.52", + "tid": 44957847 + }, + { + "amount": "0.00947867", + "date": 1595465246, + "price": "211.00", + "tid": 44957555 + }, + { + "amount": "0.00047402", + "date": 1595463523, + "price": "210.96", + "tid": 44957176 + }, + { + "amount": "0.02236510", + "date": 1595455093, + "price": "217.75", + "tid": 44953988 + }, + { + "amount": "0.00132662", + "date": 1595453653, + "price": "218.60", + "tid": 44953756 + }, + { + "amount": "0.00170178", + "date": 1595451029, + "price": "217.42", + "tid": 44952385 + }, + { + "amount": "0.00460978", + "date": 1595433874, + "price": "216.93", + "tid": 44943458 + }, + { + "amount": "0.00046098", + "date": 1595434139, + "price": "216.93", + "tid": 44943396 + }, + { + "amount": "0.00275659", + "date": 1595425795, + "price": "217.66", + "tid": 44938692 + }, + { + "amount": "0.00118765", + "date": 1595424883, + "price": "210.50", + "tid": 44938087 + }, + { + "amount": "0.00133235", + "date": 1595420796, + "price": "217.66", + "tid": 44936388 + }, + { + "amount": "0.00057709", + "date": 1595417100, + "price": "225.27", + "tid": 44935150 + }, + { + "amount": "0.00188212", + "date": 1595389095, + "price": "217.84", + "tid": 44929556 + }, + { + "amount": "0.00686499", + "date": 1595375491, + "price": "218.50", + "tid": 44926395 + }, + { + "amount": "0.01230853", + "date": 1595360031, + "price": "219.36", + "tid": 44920326 + }, + { + "amount": "0.00085559", + "date": 1595354204, + "price": "210.38", + "tid": 44916821 + }, + { + "amount": "0.00115001", + "date": 1595333293, + "price": "217.39", + "tid": 44905116 + }, + { + "amount": "0.00158824", + "date": 1595308428, + "price": "220.37", + "tid": 44899323 + }, + { + "amount": "0.00266486", + "date": 1595292754, + "price": "221.40", + "tid": 44896846 + }, + { + "amount": "0.00256364", + "date": 1595287347, + "price": "222.34", + "tid": 44895604 + }, + { + "amount": "0.00217441", + "date": 1595278943, + "price": "220.75", + "tid": 44892332 + }, + { + "amount": "0.00217441", + "date": 1595278845, + "price": "220.75", + "tid": 44892179 + }, + { + "amount": "0.00187389", + "date": 1595265693, + "price": "213.46", + "tid": 44884625 + }, + { + "amount": "0.00155202", + "date": 1595264565, + "price": "219.07", + "tid": 44884462 + }, + { + "amount": "0.00456475", + "date": 1595256755, + "price": "219.07", + "tid": 44879399 + }, + { + "amount": "0.00241932", + "date": 1595253820, + "price": "219.07", + "tid": 44877969 + }, + { + "amount": "0.00190667", + "date": 1595253112, + "price": "209.79", + "tid": 44877404 + }, + { + "amount": "0.00141831", + "date": 1595250863, + "price": "211.52", + "tid": 44876543 + }, + { + "amount": "0.15940112", + "date": 1595219371, + "price": "211.73", + "tid": 44869575 + }, + { + "amount": "0.00445900", + "date": 1595211376, + "price": "219.78", + "tid": 44868854 + }, + { + "amount": "0.00140456", + "date": 1595179233, + "price": "213.59", + "tid": 44860053 + }, + { + "amount": "0.00266751", + "date": 1595178479, + "price": "221.18", + "tid": 44859640 + }, + { + "amount": "0.00051872", + "date": 1595158010, + "price": "212.06", + "tid": 44852388 + }, + { + "amount": "0.04625915", + "date": 1595137081, + "price": "211.85", + "tid": 44848629 + }, + { + "amount": "0.00091000", + "date": 1595127872, + "price": "219.78", + "tid": 44847794 + }, + { + "amount": "0.00822218", + "date": 1595119902, + "price": "218.92", + "tid": 44846388 + }, + { + "amount": "0.00082162", + "date": 1595118324, + "price": "219.08", + "tid": 44845957 + }, + { + "amount": "0.02811903", + "date": 1595111655, + "price": "219.78", + "tid": 44844055 + }, + { + "amount": "0.13240195", + "date": 1595101530, + "price": "219.03", + "tid": 44839914 + }, + { + "amount": "0.00841751", + "date": 1595096417, + "price": "219.78", + "tid": 44837537 + }, + { + "amount": "0.00141924", + "date": 1595094339, + "price": "211.38", + "tid": 44836412 + }, + { + "amount": "0.02197652", + "date": 1595093877, + "price": "219.78", + "tid": 44836048 + }, + { + "amount": "0.01433251", + "date": 1595093910, + "price": "219.78", + "tid": 44835888 + }, + { + "amount": "0.01110201", + "date": 1595091496, + "price": "219.78", + "tid": 44834620 + }, + { + "amount": "0.00045614", + "date": 1595088368, + "price": "219.23", + "tid": 44832482 + }, + { + "amount": "0.06825007", + "date": 1595082734, + "price": "219.78", + "tid": 44829306 + }, + { + "amount": "0.00045500", + "date": 1595081906, + "price": "219.78", + "tid": 44828871 + }, + { + "amount": "0.04568713", + "date": 1595080787, + "price": "218.88", + "tid": 44827873 + }, + { + "amount": "0.00340925", + "date": 1595079027, + "price": "219.99", + "tid": 44827449 + }, + { + "amount": "0.00700723", + "date": 1595078417, + "price": "221.20", + "tid": 44827205 + }, + { + "amount": "0.00054304", + "date": 1595078120, + "price": "220.98", + "tid": 44827044 + }, + { + "amount": "0.00049778", + "date": 1595066737, + "price": "220.98", + "tid": 44823391 + }, + { + "amount": "0.00525347", + "date": 1595061729, + "price": "222.71", + "tid": 44822243 + }, + { + "amount": "0.00152665", + "date": 1595040852, + "price": "222.71", + "tid": 44819000 + }, + { + "amount": "0.00141563", + "date": 1595030853, + "price": "211.92", + "tid": 44816503 + }, + { + "amount": "0.01162005", + "date": 1595020816, + "price": "222.03", + "tid": 44812585 + }, + { + "amount": "0.00212930", + "date": 1595019854, + "price": "220.73", + "tid": 44812355 + }, + { + "amount": "0.00452612", + "date": 1595017473, + "price": "220.94", + "tid": 44810901 + }, + { + "amount": "0.00701548", + "date": 1595016056, + "price": "220.94", + "tid": 44810160 + }, + { + "amount": "0.00054365", + "date": 1595011841, + "price": "220.73", + "tid": 44807799 + }, + { + "amount": "0.00126852", + "date": 1595009917, + "price": "220.73", + "tid": 44806826 + }, + { + "amount": "0.00433233", + "date": 1595003107, + "price": "221.59", + "tid": 44801982 + }, + { + "amount": "0.00906084", + "date": 1594999732, + "price": "220.73", + "tid": 44799115 + }, + { + "amount": "0.00121698", + "date": 1594950270, + "price": "221.86", + "tid": 44784777 + }, + { + "amount": "0.03231768", + "date": 1594947924, + "price": "221.86", + "tid": 44784429 + }, + { + "amount": "0.00302948", + "date": 1594941121, + "price": "221.16", + "tid": 44781823 + }, + { + "amount": "0.01487425", + "date": 1594941135, + "price": "221.86", + "tid": 44781712 + }, + { + "amount": "0.01235344", + "date": 1594934832, + "price": "222.61", + "tid": 44779182 + }, + { + "amount": "0.00429864", + "date": 1594918001, + "price": "221.00", + "tid": 44769862 + }, + { + "amount": "0.00334176", + "date": 1594912092, + "price": "221.44", + "tid": 44765451 + }, + { + "amount": "0.00045126", + "date": 1594909574, + "price": "221.60", + "tid": 44764017 + }, + { + "amount": "0.00265754", + "date": 1594904494, + "price": "222.01", + "tid": 44761518 + }, + { + "amount": "0.00045104", + "date": 1594900598, + "price": "221.71", + "tid": 44759861 + }, + { + "amount": "0.00358986", + "date": 1594884991, + "price": "222.85", + "tid": 44755547 + }, + { + "amount": "0.01212037", + "date": 1594877058, + "price": "216.99", + "tid": 44754170 + }, + { + "amount": "0.00046085", + "date": 1594862487, + "price": "216.99", + "tid": 44751969 + }, + { + "amount": "0.00096828", + "date": 1594847892, + "price": "216.88", + "tid": 44746392 + }, + { + "amount": "0.00507263", + "date": 1594843067, + "price": "216.85", + "tid": 44743502 + }, + { + "amount": "0.00045975", + "date": 1594841653, + "price": "217.51", + "tid": 44743183 + }, + { + "amount": "0.02596780", + "date": 1594821864, + "price": "208.72", + "tid": 44730832 + }, + { + "amount": "0.00101852", + "date": 1594757596, + "price": "216.00", + "tid": 44710507 + }, + { + "amount": "0.01942379", + "date": 1594753391, + "price": "215.20", + "tid": 44708503 + }, + { + "amount": "0.06970260", + "date": 1594752935, + "price": "215.20", + "tid": 44707793 + }, + { + "amount": "0.06970260", + "date": 1594752772, + "price": "215.20", + "tid": 44707739 + }, + { + "amount": "0.00106358", + "date": 1594738452, + "price": "216.25", + "tid": 44698235 + }, + { + "amount": "0.00092855", + "date": 1594736057, + "price": "215.39", + "tid": 44696531 + }, + { + "amount": "0.01025546", + "date": 1594713690, + "price": "216.47", + "tid": 44688485 + }, + { + "amount": "0.00046196", + "date": 1594713498, + "price": "216.47", + "tid": 44688318 + }, + { + "amount": "0.00460358", + "date": 1594690090, + "price": "215.05", + "tid": 44686470 + }, + { + "amount": "0.00209644", + "date": 1594671448, + "price": "214.65", + "tid": 44679161 + }, + { + "amount": "0.03564131", + "date": 1594667306, + "price": "210.43", + "tid": 44676373 + }, + { + "amount": "0.00249181", + "date": 1594666097, + "price": "216.71", + "tid": 44675746 + }, + { + "amount": "0.00152156", + "date": 1594663069, + "price": "210.31", + "tid": 44674285 + }, + { + "amount": "0.00521747", + "date": 1594662573, + "price": "210.83", + "tid": 44673744 + }, + { + "amount": "0.00213280", + "date": 1594625661, + "price": "210.99", + "tid": 44657533 + }, + { + "amount": "0.00286802", + "date": 1594589183, + "price": "212.69", + "tid": 44651620 + }, + { + "amount": "0.01119667", + "date": 1594585945, + "price": "211.67", + "tid": 44650777 + }, + { + "amount": "0.00253962", + "date": 1594584254, + "price": "212.63", + "tid": 44650270 + }, + { + "amount": "0.00234929", + "date": 1594582344, + "price": "212.83", + "tid": 44649613 + }, + { + "amount": "0.02936587", + "date": 1594581359, + "price": "211.47", + "tid": 44649222 + }, + { + "amount": "0.00518501", + "date": 1594571176, + "price": "212.15", + "tid": 44645081 + }, + { + "amount": "0.00057091", + "date": 1594557144, + "price": "210.19", + "tid": 44640222 + }, + { + "amount": "0.00423091", + "date": 1594485235, + "price": "212.72", + "tid": 44621415 + }, + { + "amount": "0.00197266", + "date": 1594480978, + "price": "212.91", + "tid": 44618812 + }, + { + "amount": "0.00490242", + "date": 1594471831, + "price": "212.14", + "tid": 44614817 + }, + { + "amount": "0.00168547", + "date": 1594436069, + "price": "213.59", + "tid": 44607350 + }, + { + "amount": "0.00253022", + "date": 1594419734, + "price": "213.42", + "tid": 44602772 + }, + { + "amount": "0.00051542", + "date": 1594410338, + "price": "213.42", + "tid": 44598184 + }, + { + "amount": "0.00217043", + "date": 1594409426, + "price": "211.94", + "tid": 44597803 + }, + { + "amount": "0.00391620", + "date": 1594409523, + "price": "211.94", + "tid": 44597796 + }, + { + "amount": "0.00146268", + "date": 1594407068, + "price": "211.94", + "tid": 44595878 + }, + { + "amount": "0.00080094", + "date": 1594392377, + "price": "212.25", + "tid": 44585935 + }, + { + "amount": "0.02272505", + "date": 1594379818, + "price": "204.18", + "tid": 44579808 + }, + { + "amount": "0.00126027", + "date": 1594349056, + "price": "214.24", + "tid": 44573529 + }, + { + "amount": "0.00121359", + "date": 1594346549, + "price": "214.24", + "tid": 44573209 + }, + { + "amount": "0.00186706", + "date": 1594346055, + "price": "214.24", + "tid": 44573081 + }, + { + "amount": "0.00470943", + "date": 1594343715, + "price": "212.34", + "tid": 44572577 + }, + { + "amount": "0.00252054", + "date": 1594343055, + "price": "214.24", + "tid": 44572456 + }, + { + "amount": "0.05274459", + "date": 1594330094, + "price": "214.24", + "tid": 44567944 + }, + { + "amount": "0.00133295", + "date": 1594304918, + "price": "210.06", + "tid": 44553439 + }, + { + "amount": "0.00166144", + "date": 1594295799, + "price": "210.66", + "tid": 44549875 + }, + { + "amount": "0.00108281", + "date": 1594254737, + "price": "212.41", + "tid": 44541712 + }, + { + "amount": "0.00579915", + "date": 1594253063, + "price": "212.10", + "tid": 44541252 + }, + { + "amount": "0.01050838", + "date": 1594235162, + "price": "211.26", + "tid": 44532694 + }, + { + "amount": "0.00127467", + "date": 1594234644, + "price": "211.82", + "tid": 44532385 + }, + { + "amount": "0.00056762", + "date": 1594217002, + "price": "211.41", + "tid": 44521189 + }, + { + "amount": "0.00415938", + "date": 1594214537, + "price": "211.57", + "tid": 44520075 + }, + { + "amount": "0.00052421", + "date": 1594212501, + "price": "209.84", + "tid": 44519091 + }, + { + "amount": "0.00653221", + "date": 1594206789, + "price": "209.73", + "tid": 44517028 + }, + { + "amount": "0.00950228", + "date": 1594161098, + "price": "216.79", + "tid": 44507222 + }, + { + "amount": "0.00110162", + "date": 1594159280, + "price": "217.86", + "tid": 44506590 + }, + { + "amount": "0.00555160", + "date": 1594159654, + "price": "210.75", + "tid": 44506394 + }, + { + "amount": "0.00105572", + "date": 1594158503, + "price": "217.86", + "tid": 44506235 + }, + { + "amount": "0.01060314", + "date": 1594157991, + "price": "217.86", + "tid": 44505910 + }, + { + "amount": "0.00220325", + "date": 1594156385, + "price": "217.86", + "tid": 44505387 + }, + { + "amount": "0.01614466", + "date": 1594157076, + "price": "216.79", + "tid": 44505324 + }, + { + "amount": "0.00083169", + "date": 1594138641, + "price": "228.45", + "tid": 44493535 + }, + { + "amount": "0.00115554", + "date": 1594127420, + "price": "216.35", + "tid": 44487564 + }, + { + "amount": "0.00100876", + "date": 1594075597, + "price": "218.09", + "tid": 44475045 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] } } } \ No newline at end of file diff --git a/testdata/http_mock/poloniex/poloniex.json b/testdata/http_mock/poloniex/poloniex.json index 30099cc3..86bd00c2 100644 --- a/testdata/http_mock/poloniex/poloniex.json +++ b/testdata/http_mock/poloniex/poloniex.json @@ -2356,2013 +2356,6 @@ "bodyParams": "", "headers": {} }, - { - "data": [ - { - "amount": "3.67796814", - "date": "2019-06-11 04:31:22", - "globalTradeID": 419660422, - "orderNumber": 378714356664, - "rate": "0.01087441", - "total": "0.03999573", - "tradeID": 19495952, - "type": "buy" - }, - { - "amount": "0.00571394", - "date": "2019-06-11 04:30:31", - "globalTradeID": 419660404, - "orderNumber": 378714099921, - "rate": "0.01086990", - "total": "0.00006210", - "tradeID": 19495951, - "type": "sell" - }, - { - "amount": "0.00230268", - "date": "2019-06-11 04:30:26", - "globalTradeID": 419660400, - "orderNumber": 378714088932, - "rate": "0.01086990", - "total": "0.00002502", - "tradeID": 19495950, - "type": "sell" - }, - { - "amount": "0.09199674", - "date": "2019-06-11 04:30:07", - "globalTradeID": 419660390, - "orderNumber": 378714018003, - "rate": "0.01086995", - "total": "0.00099999", - "tradeID": 19495949, - "type": "buy" - }, - { - "amount": "0.18399348", - "date": "2019-06-11 04:29:44", - "globalTradeID": 419660384, - "orderNumber": 378713958063, - "rate": "0.01086995", - "total": "0.00199999", - "tradeID": 19495948, - "type": "buy" - }, - { - "amount": "0.00921345", - "date": "2019-06-11 04:27:43", - "globalTradeID": 419660320, - "orderNumber": 378713556465, - "rate": "0.01086995", - "total": "0.00010014", - "tradeID": 19495947, - "type": "buy" - }, - { - "amount": "0.00977015", - "date": "2019-06-11 04:27:16", - "globalTradeID": 419660311, - "orderNumber": 378713374647, - "rate": "0.01087360", - "total": "0.00010623", - "tradeID": 19495946, - "type": "sell" - }, - { - "amount": "0.00059317", - "date": "2019-06-11 04:27:08", - "globalTradeID": 419660294, - "orderNumber": 378713343678, - "rate": "0.01087361", - "total": "0.00000644", - "tradeID": 19495945, - "type": "sell" - }, - { - "amount": "0.09193288", - "date": "2019-06-11 04:25:46", - "globalTradeID": 419660267, - "orderNumber": 378713085936, - "rate": "0.01087743", - "total": "0.00099999", - "tradeID": 19495944, - "type": "buy" - }, - { - "amount": "0.00391038", - "date": "2019-06-11 04:25:30", - "globalTradeID": 419660245, - "orderNumber": 378712987035, - "rate": "0.01087360", - "total": "0.00004251", - "tradeID": 19495943, - "type": "sell" - }, - { - "amount": "0.18386391", - "date": "2019-06-11 04:25:30", - "globalTradeID": 419660244, - "orderNumber": 378712985037, - "rate": "0.01087756", - "total": "0.00199999", - "tradeID": 19495942, - "type": "buy" - }, - { - "amount": "0.01369197", - "date": "2019-06-11 04:25:00", - "globalTradeID": 419660236, - "orderNumber": 378712820202, - "rate": "0.01088420", - "total": "0.00014902", - "tradeID": 19495941, - "type": "sell" - }, - { - "amount": "0.01427388", - "date": "2019-06-11 04:24:35", - "globalTradeID": 419660229, - "orderNumber": 378712682340, - "rate": "0.01088519", - "total": "0.00015537", - "tradeID": 19495940, - "type": "sell" - }, - { - "amount": "0.00097304", - "date": "2019-06-11 04:24:34", - "globalTradeID": 419660226, - "orderNumber": 378712674348, - "rate": "0.01088768", - "total": "0.00001059", - "tradeID": 19495939, - "type": "sell" - }, - { - "amount": "1.48700000", - "date": "2019-06-11 04:22:05", - "globalTradeID": 419660173, - "orderNumber": 378711816207, - "rate": "0.01088769", - "total": "0.01618999", - "tradeID": 19495938, - "type": "sell" - }, - { - "amount": "1.31174004", - "date": "2019-06-11 04:22:02", - "globalTradeID": 419660171, - "orderNumber": 378711803220, - "rate": "0.01088768", - "total": "0.01428180", - "tradeID": 19495937, - "type": "sell" - }, - { - "amount": "0.01425996", - "date": "2019-06-11 04:22:02", - "globalTradeID": 419660170, - "orderNumber": 378711803220, - "rate": "0.01089626", - "total": "0.00015538", - "tradeID": 19495936, - "type": "sell" - }, - { - "amount": "5.95100000", - "date": "2019-06-11 04:20:05", - "globalTradeID": 419660132, - "orderNumber": 378711129894, - "rate": "0.01089627", - "total": "0.06484370", - "tradeID": 19495935, - "type": "sell" - }, - { - "amount": "3.65950000", - "date": "2019-06-11 04:20:05", - "globalTradeID": 419660131, - "orderNumber": 378711122901, - "rate": "0.01089627", - "total": "0.03987490", - "tradeID": 19495934, - "type": "sell" - }, - { - "amount": "0.16900000", - "date": "2019-06-11 04:20:01", - "globalTradeID": 419660129, - "orderNumber": 378711079944, - "rate": "0.01091500", - "total": "0.00184463", - "tradeID": 19495933, - "type": "sell" - }, - { - "amount": "21.93500000", - "date": "2019-06-11 04:20:01", - "globalTradeID": 419660126, - "orderNumber": 378711075948, - "rate": "0.01091935", - "total": "0.23951594", - "tradeID": 19495932, - "type": "sell" - }, - { - "amount": "11.44500000", - "date": "2019-06-11 04:20:01", - "globalTradeID": 419660124, - "orderNumber": 378711073950, - "rate": "0.01091935", - "total": "0.12497196", - "tradeID": 19495931, - "type": "sell" - }, - { - "amount": "37.87000000", - "date": "2019-06-11 04:20:00", - "globalTradeID": 419660123, - "orderNumber": 378711071952, - "rate": "0.01091935", - "total": "0.41351578", - "tradeID": 19495930, - "type": "sell" - }, - { - "amount": "0.11441976", - "date": "2019-06-11 04:20:00", - "globalTradeID": 419660122, - "orderNumber": 378711070953, - "rate": "0.01091937", - "total": "0.00124939", - "tradeID": 19495929, - "type": "sell" - }, - { - "amount": "0.00001589", - "date": "2019-06-11 04:19:08", - "globalTradeID": 419660106, - "orderNumber": 378710872152, - "rate": "0.01092168", - "total": "0.00000017", - "tradeID": 19495928, - "type": "buy" - }, - { - "amount": "0.00000361", - "date": "2019-06-11 04:17:33", - "globalTradeID": 419660079, - "orderNumber": 378710442582, - "rate": "0.01094157", - "total": "0.00000003", - "tradeID": 19495927, - "type": "buy" - }, - { - "amount": "0.10771685", - "date": "2019-06-11 04:17:25", - "globalTradeID": 419660064, - "orderNumber": 378710362662, - "rate": "0.01094825", - "total": "0.00117931", - "tradeID": 19495926, - "type": "buy" - }, - { - "amount": "0.00038186", - "date": "2019-06-11 04:17:17", - "globalTradeID": 419660041, - "orderNumber": 378710310714, - "rate": "0.01092001", - "total": "0.00000416", - "tradeID": 19495925, - "type": "buy" - }, - { - "amount": "0.00020349", - "date": "2019-06-11 04:17:17", - "globalTradeID": 419660040, - "orderNumber": 378710310714, - "rate": "0.01092000", - "total": "0.00000222", - "tradeID": 19495924, - "type": "buy" - }, - { - "amount": "0.05500000", - "date": "2019-06-11 04:17:15", - "globalTradeID": 419660037, - "orderNumber": 378710295729, - "rate": "0.01092000", - "total": "0.00060060", - "tradeID": 19495923, - "type": "buy" - }, - { - "amount": "13.40208261", - "date": "2019-06-11 04:15:16", - "globalTradeID": 419659984, - "orderNumber": 378709791234, - "rate": "0.01091912", - "total": "0.14633894", - "tradeID": 19495922, - "type": "sell" - }, - { - "amount": "0.00003551", - "date": "2019-06-11 04:14:24", - "globalTradeID": 419659967, - "orderNumber": 378709500525, - "rate": "0.01092001", - "total": "0.00000038", - "tradeID": 19495921, - "type": "buy" - }, - { - "amount": "0.05223877", - "date": "2019-06-11 04:12:52", - "globalTradeID": 419659939, - "orderNumber": 378709035990, - "rate": "0.01091700", - "total": "0.00057029", - "tradeID": 19495920, - "type": "sell" - }, - { - "amount": "0.11400000", - "date": "2019-06-11 04:11:42", - "globalTradeID": 419659917, - "orderNumber": 378708709317, - "rate": "0.01092001", - "total": "0.00124488", - "tradeID": 19495919, - "type": "buy" - }, - { - "amount": "0.59200000", - "date": "2019-06-11 04:10:11", - "globalTradeID": 419659887, - "orderNumber": 378708191835, - "rate": "0.01092641", - "total": "0.00646843", - "tradeID": 19495918, - "type": "buy" - }, - { - "amount": "8.04867515", - "date": "2019-06-11 04:09:36", - "globalTradeID": 419659868, - "orderNumber": 378707979048, - "rate": "0.01090201", - "total": "0.08774673", - "tradeID": 19495917, - "type": "sell" - }, - { - "amount": "0.11441976", - "date": "2019-06-11 04:09:36", - "globalTradeID": 419659867, - "orderNumber": 378707979048, - "rate": "0.01090202", - "total": "0.00124740", - "tradeID": 19495916, - "type": "sell" - }, - { - "amount": "2.31990509", - "date": "2019-06-11 04:09:36", - "globalTradeID": 419659866, - "orderNumber": 378707979048, - "rate": "0.01090310", - "total": "0.02529415", - "tradeID": 19495915, - "type": "sell" - }, - { - "amount": "0.01700000", - "date": "2019-06-11 04:09:36", - "globalTradeID": 419659865, - "orderNumber": 378707979048, - "rate": "0.01092004", - "total": "0.00018564", - "tradeID": 19495914, - "type": "sell" - }, - { - "amount": "0.01418870", - "date": "2019-06-11 04:07:31", - "globalTradeID": 419659807, - "orderNumber": 378707249778, - "rate": "0.01095075", - "total": "0.00015537", - "tradeID": 19495913, - "type": "sell" - }, - { - "amount": "0.04206385", - "date": "2019-06-11 04:05:05", - "globalTradeID": 419659769, - "orderNumber": 378706749279, - "rate": "0.01096500", - "total": "0.00046123", - "tradeID": 19495912, - "type": "sell" - }, - { - "amount": "0.00000182", - "date": "2019-06-11 04:00:04", - "globalTradeID": 419659591, - "orderNumber": 378705401628, - "rate": "0.01096866", - "total": "0.00000001", - "tradeID": 19495911, - "type": "buy" - }, - { - "amount": "0.00131691", - "date": "2019-06-11 03:58:27", - "globalTradeID": 419659509, - "orderNumber": 378705024006, - "rate": "0.01096500", - "total": "0.00001443", - "tradeID": 19495910, - "type": "sell" - }, - { - "amount": "0.00000503", - "date": "2019-06-11 03:56:54", - "globalTradeID": 419659489, - "orderNumber": 378704656374, - "rate": "0.01096874", - "total": "0.00000005", - "tradeID": 19495909, - "type": "buy" - }, - { - "amount": "0.00095029", - "date": "2019-06-11 03:56:52", - "globalTradeID": 419659483, - "orderNumber": 378704634396, - "rate": "0.01096500", - "total": "0.00001041", - "tradeID": 19495908, - "type": "sell" - }, - { - "amount": "0.77346138", - "date": "2019-06-11 03:55:53", - "globalTradeID": 419659466, - "orderNumber": 378704373657, - "rate": "0.01096886", - "total": "0.00848398", - "tradeID": 19495907, - "type": "buy" - }, - { - "amount": "0.13853132", - "date": "2019-06-11 03:55:53", - "globalTradeID": 419659465, - "orderNumber": 378704373657, - "rate": "0.01096885", - "total": "0.00151952", - "tradeID": 19495906, - "type": "buy" - }, - { - "amount": "0.00000182", - "date": "2019-06-11 03:55:18", - "globalTradeID": 419659451, - "orderNumber": 378704154876, - "rate": "0.01097328", - "total": "0.00000001", - "tradeID": 19495905, - "type": "buy" - }, - { - "amount": "0.00323397", - "date": "2019-06-11 03:53:35", - "globalTradeID": 419659388, - "orderNumber": 378703612419, - "rate": "0.01097102", - "total": "0.00003547", - "tradeID": 19495904, - "type": "sell" - }, - { - "amount": "0.01121592", - "date": "2019-06-11 03:53:35", - "globalTradeID": 419659387, - "orderNumber": 378703612419, - "rate": "0.01097102", - "total": "0.00012305", - "tradeID": 19495903, - "type": "sell" - }, - { - "amount": "0.00000551", - "date": "2019-06-11 03:51:59", - "globalTradeID": 419659361, - "orderNumber": 378703243788, - "rate": "0.01097329", - "total": "0.00000006", - "tradeID": 19495902, - "type": "buy" - }, - { - "amount": "0.00000302", - "date": "2019-06-11 03:50:22", - "globalTradeID": 419659311, - "orderNumber": 378702896136, - "rate": "0.01097337", - "total": "0.00000003", - "tradeID": 19495901, - "type": "buy" - }, - { - "amount": "0.00001640", - "date": "2019-06-11 03:50:19", - "globalTradeID": 419659308, - "orderNumber": 378702885147, - "rate": "0.01097102", - "total": "0.00000017", - "tradeID": 19495900, - "type": "sell" - }, - { - "amount": "0.02814583", - "date": "2019-06-11 03:49:39", - "globalTradeID": 419659273, - "orderNumber": 378702765267, - "rate": "0.01097341", - "total": "0.00030885", - "tradeID": 19495899, - "type": "buy" - }, - { - "amount": "0.00000202", - "date": "2019-06-11 03:48:46", - "globalTradeID": 419659247, - "orderNumber": 378702529503, - "rate": "0.01097347", - "total": "0.00000002", - "tradeID": 19495898, - "type": "buy" - }, - { - "amount": "0.00000903", - "date": "2019-06-11 03:47:11", - "globalTradeID": 419659206, - "orderNumber": 378702105927, - "rate": "0.01098449", - "total": "0.00000009", - "tradeID": 19495897, - "type": "buy" - }, - { - "amount": "0.00114936", - "date": "2019-06-11 03:47:06", - "globalTradeID": 419659201, - "orderNumber": 378702095937, - "rate": "0.01097123", - "total": "0.00001260", - "tradeID": 19495896, - "type": "sell" - }, - { - "amount": "0.00000607", - "date": "2019-06-11 03:45:33", - "globalTradeID": 419659162, - "orderNumber": 378701612421, - "rate": "0.01098220", - "total": "0.00000006", - "tradeID": 19495895, - "type": "buy" - }, - { - "amount": "0.00001116", - "date": "2019-06-11 03:43:57", - "globalTradeID": 419659121, - "orderNumber": 378701091942, - "rate": "0.01098466", - "total": "0.00000012", - "tradeID": 19495894, - "type": "buy" - }, - { - "amount": "0.00000381", - "date": "2019-06-11 03:42:20", - "globalTradeID": 419659098, - "orderNumber": 378700626408, - "rate": "0.01098497", - "total": "0.00000004", - "tradeID": 19495893, - "type": "buy" - }, - { - "amount": "0.00000521", - "date": "2019-06-11 03:39:06", - "globalTradeID": 419659053, - "orderNumber": 378699644391, - "rate": "0.01098849", - "total": "0.00000005", - "tradeID": 19495892, - "type": "buy" - }, - { - "amount": "1.56192145", - "date": "2019-06-11 03:37:49", - "globalTradeID": 419659027, - "orderNumber": 378699299736, - "rate": "0.01098390", - "total": "0.01715598", - "tradeID": 19495891, - "type": "buy" - }, - { - "amount": "0.00000203", - "date": "2019-06-11 03:37:30", - "globalTradeID": 419659020, - "orderNumber": 378699228807, - "rate": "0.01098390", - "total": "0.00000002", - "tradeID": 19495890, - "type": "buy" - }, - { - "amount": "1.82224405", - "date": "2019-06-11 03:37:09", - "globalTradeID": 419659010, - "orderNumber": 378699142893, - "rate": "0.01098499", - "total": "0.02001733", - "tradeID": 19495889, - "type": "buy" - }, - { - "amount": "0.63389687", - "date": "2019-06-11 03:37:09", - "globalTradeID": 419659009, - "orderNumber": 378699142893, - "rate": "0.01097301", - "total": "0.00695575", - "tradeID": 19495888, - "type": "buy" - }, - { - "amount": "0.00000313", - "date": "2019-06-11 03:35:52", - "globalTradeID": 419658982, - "orderNumber": 378698852184, - "rate": "0.01097301", - "total": "0.00000003", - "tradeID": 19495887, - "type": "buy" - }, - { - "amount": "0.00000343", - "date": "2019-06-11 03:34:14", - "globalTradeID": 419658951, - "orderNumber": 378698676360, - "rate": "0.01097401", - "total": "0.00000003", - "tradeID": 19495886, - "type": "buy" - }, - { - "amount": "0.00003856", - "date": "2019-06-11 03:32:36", - "globalTradeID": 419658906, - "orderNumber": 378698162874, - "rate": "0.01098544", - "total": "0.00000042", - "tradeID": 19495885, - "type": "buy" - }, - { - "amount": "0.00000822", - "date": "2019-06-11 03:30:54", - "globalTradeID": 419658856, - "orderNumber": 378697679358, - "rate": "0.01100470", - "total": "0.00000009", - "tradeID": 19495884, - "type": "buy" - }, - { - "amount": "0.00005336", - "date": "2019-06-11 03:27:44", - "globalTradeID": 419658782, - "orderNumber": 378696543495, - "rate": "0.01099742", - "total": "0.00000058", - "tradeID": 19495883, - "type": "buy" - }, - { - "amount": "1.59326119", - "date": "2019-06-11 03:25:32", - "globalTradeID": 419658690, - "orderNumber": 378696202836, - "rate": "0.01099155", - "total": "0.01751241", - "tradeID": 19495882, - "type": "buy" - }, - { - "amount": "0.00000776", - "date": "2019-06-11 03:22:57", - "globalTradeID": 419658624, - "orderNumber": 378695513526, - "rate": "0.01100279", - "total": "0.00000008", - "tradeID": 19495881, - "type": "buy" - }, - { - "amount": "0.00181536", - "date": "2019-06-11 03:21:18", - "globalTradeID": 419658597, - "orderNumber": 378694987053, - "rate": "0.01099501", - "total": "0.00001995", - "tradeID": 19495880, - "type": "sell" - }, - { - "amount": "0.00000823", - "date": "2019-06-11 03:18:10", - "globalTradeID": 419658524, - "orderNumber": 378694251789, - "rate": "0.01102096", - "total": "0.00000009", - "tradeID": 19495879, - "type": "buy" - }, - { - "amount": "0.04754874", - "date": "2019-06-11 03:16:43", - "globalTradeID": 419658405, - "orderNumber": 378693959082, - "rate": "0.01100509", - "total": "0.00052327", - "tradeID": 19495878, - "type": "sell" - }, - { - "amount": "0.63690866", - "date": "2019-06-11 03:15:56", - "globalTradeID": 419658370, - "orderNumber": 378693752289, - "rate": "0.01099326", - "total": "0.00700170", - "tradeID": 19495877, - "type": "sell" - }, - { - "amount": "0.11409631", - "date": "2019-06-11 03:15:56", - "globalTradeID": 419658369, - "orderNumber": 378693752289, - "rate": "0.01099501", - "total": "0.00125449", - "tradeID": 19495876, - "type": "sell" - }, - { - "amount": "0.01688839", - "date": "2019-06-11 03:15:56", - "globalTradeID": 419658368, - "orderNumber": 378693752289, - "rate": "0.01099826", - "total": "0.00018574", - "tradeID": 19495875, - "type": "sell" - }, - { - "amount": "0.15215954", - "date": "2019-06-11 03:15:56", - "globalTradeID": 419658367, - "orderNumber": 378693752289, - "rate": "0.01102244", - "total": "0.00167716", - "tradeID": 19495874, - "type": "sell" - }, - { - "amount": "0.21255099", - "date": "2019-06-11 03:15:10", - "globalTradeID": 419658294, - "orderNumber": 378693585456, - "rate": "0.01102244", - "total": "0.00234283", - "tradeID": 19495873, - "type": "buy" - }, - { - "amount": "0.00019436", - "date": "2019-06-11 03:14:56", - "globalTradeID": 419658268, - "orderNumber": 378693515526, - "rate": "0.01101010", - "total": "0.00000213", - "tradeID": 19495872, - "type": "sell" - }, - { - "amount": "0.00000181", - "date": "2019-06-11 03:08:32", - "globalTradeID": 419658029, - "orderNumber": 378691456587, - "rate": "0.01100114", - "total": "0.00000001", - "tradeID": 19495871, - "type": "sell" - }, - { - "amount": "0.00101626", - "date": "2019-06-11 03:08:29", - "globalTradeID": 419658023, - "orderNumber": 378691443600, - "rate": "0.01100112", - "total": "0.00001117", - "tradeID": 19495870, - "type": "sell" - }, - { - "amount": "0.00026088", - "date": "2019-06-11 03:08:23", - "globalTradeID": 419658017, - "orderNumber": 378691431612, - "rate": "0.01100110", - "total": "0.00000286", - "tradeID": 19495869, - "type": "sell" - }, - { - "amount": "0.00016545", - "date": "2019-06-11 03:06:50", - "globalTradeID": 419657999, - "orderNumber": 378691103940, - "rate": "0.01100023", - "total": "0.00000181", - "tradeID": 19495868, - "type": "sell" - }, - { - "amount": "0.00023999", - "date": "2019-06-11 03:06:49", - "globalTradeID": 419657996, - "orderNumber": 378691102941, - "rate": "0.01100023", - "total": "0.00000263", - "tradeID": 19495867, - "type": "sell" - }, - { - "amount": "0.00011456", - "date": "2019-06-11 02:58:48", - "globalTradeID": 419657740, - "orderNumber": 378689243802, - "rate": "0.01099843", - "total": "0.00000125", - "tradeID": 19495866, - "type": "sell" - }, - { - "amount": "0.03917163", - "date": "2019-06-11 02:56:40", - "globalTradeID": 419657701, - "orderNumber": 378688729317, - "rate": "0.01101556", - "total": "0.00043149", - "tradeID": 19495865, - "type": "buy" - }, - { - "amount": "0.13679308", - "date": "2019-06-11 02:53:35", - "globalTradeID": 419657601, - "orderNumber": 378687637410, - "rate": "0.01101519", - "total": "0.00150680", - "tradeID": 19495864, - "type": "sell" - }, - { - "amount": "0.01058570", - "date": "2019-06-11 02:50:54", - "globalTradeID": 419657476, - "orderNumber": 378686860188, - "rate": "0.01101013", - "total": "0.00011654", - "tradeID": 19495863, - "type": "sell" - }, - { - "amount": "0.04280000", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657453, - "orderNumber": 378686618430, - "rate": "0.01101828", - "total": "0.00047158", - "tradeID": 19495862, - "type": "buy" - }, - { - "amount": "0.01398753", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657452, - "orderNumber": 378686618430, - "rate": "0.01101780", - "total": "0.00015411", - "tradeID": 19495861, - "type": "buy" - }, - { - "amount": "2.39150539", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657451, - "orderNumber": 378686618430, - "rate": "0.01101629", - "total": "0.02634551", - "tradeID": 19495860, - "type": "buy" - }, - { - "amount": "0.01340400", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657450, - "orderNumber": 378686618430, - "rate": "0.01101230", - "total": "0.00014760", - "tradeID": 19495859, - "type": "buy" - }, - { - "amount": "0.16756661", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657449, - "orderNumber": 378686618430, - "rate": "0.01100868", - "total": "0.00184468", - "tradeID": 19495858, - "type": "buy" - }, - { - "amount": "0.01390076", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657448, - "orderNumber": 378686618430, - "rate": "0.01100810", - "total": "0.00015302", - "tradeID": 19495857, - "type": "buy" - }, - { - "amount": "0.01411744", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657447, - "orderNumber": 378686618430, - "rate": "0.01100551", - "total": "0.00015536", - "tradeID": 19495856, - "type": "buy" - }, - { - "amount": "0.04273596", - "date": "2019-06-11 02:50:18", - "globalTradeID": 419657445, - "orderNumber": 378686615433, - "rate": "0.01100543", - "total": "0.00047032", - "tradeID": 19495855, - "type": "buy" - }, - { - "amount": "0.01515621", - "date": "2019-06-11 02:45:31", - "globalTradeID": 419657298, - "orderNumber": 378685060989, - "rate": "0.01100142", - "total": "0.00016673", - "tradeID": 19495854, - "type": "buy" - }, - { - "amount": "0.01395757", - "date": "2019-06-11 02:44:56", - "globalTradeID": 419657290, - "orderNumber": 378684828222, - "rate": "0.01100060", - "total": "0.00015354", - "tradeID": 19495853, - "type": "buy" - }, - { - "amount": "0.07110823", - "date": "2019-06-11 02:39:35", - "globalTradeID": 419657119, - "orderNumber": 378683079972, - "rate": "0.01099521", - "total": "0.00078184", - "tradeID": 19495852, - "type": "sell" - }, - { - "amount": "0.00017289", - "date": "2019-06-11 02:38:00", - "globalTradeID": 419657062, - "orderNumber": 378682556496, - "rate": "0.01098911", - "total": "0.00000189", - "tradeID": 19495851, - "type": "sell" - }, - { - "amount": "0.28712708", - "date": "2019-06-11 02:37:35", - "globalTradeID": 419657049, - "orderNumber": 378682396656, - "rate": "0.01100000", - "total": "0.00315839", - "tradeID": 19495850, - "type": "buy" - }, - { - "amount": "11.98089159", - "date": "2019-06-11 02:37:35", - "globalTradeID": 419657048, - "orderNumber": 378682396656, - "rate": "0.01100000", - "total": "0.13178980", - "tradeID": 19495849, - "type": "buy" - }, - { - "amount": "20.28670000", - "date": "2019-06-11 02:37:35", - "globalTradeID": 419657047, - "orderNumber": 378682391661, - "rate": "0.01100000", - "total": "0.22315370", - "tradeID": 19495848, - "type": "buy" - }, - { - "amount": "19.58857431", - "date": "2019-06-11 02:37:23", - "globalTradeID": 419657037, - "orderNumber": 378682329723, - "rate": "0.01100000", - "total": "0.21547431", - "tradeID": 19495847, - "type": "buy" - }, - { - "amount": "0.10000400", - "date": "2019-06-11 02:37:23", - "globalTradeID": 419657036, - "orderNumber": 378682329723, - "rate": "0.01100000", - "total": "0.00110004", - "tradeID": 19495846, - "type": "buy" - }, - { - "amount": "0.10000000", - "date": "2019-06-11 02:37:23", - "globalTradeID": 419657035, - "orderNumber": 378682329723, - "rate": "0.01099996", - "total": "0.00109999", - "tradeID": 19495845, - "type": "buy" - }, - { - "amount": "0.09091165", - "date": "2019-06-11 02:37:23", - "globalTradeID": 419657034, - "orderNumber": 378682329723, - "rate": "0.01099969", - "total": "0.00099999", - "tradeID": 19495844, - "type": "buy" - }, - { - "amount": "2.39651004", - "date": "2019-06-11 02:37:23", - "globalTradeID": 419657033, - "orderNumber": 378682329723, - "rate": "0.01099922", - "total": "0.02635974", - "tradeID": 19495843, - "type": "buy" - }, - { - "amount": "1.02574734", - "date": "2019-06-11 02:37:02", - "globalTradeID": 419657007, - "orderNumber": 378682212840, - "rate": "0.01099588", - "total": "0.01127899", - "tradeID": 19495842, - "type": "buy" - }, - { - "amount": "0.27600000", - "date": "2019-06-11 02:36:41", - "globalTradeID": 419656977, - "orderNumber": 378682057995, - "rate": "0.01099588", - "total": "0.00303486", - "tradeID": 19495841, - "type": "buy" - }, - { - "amount": "2.76229338", - "date": "2019-06-11 02:36:09", - "globalTradeID": 419656960, - "orderNumber": 378681860193, - "rate": "0.01098950", - "total": "0.03035622", - "tradeID": 19495840, - "type": "buy" - }, - { - "amount": "0.00085253", - "date": "2019-06-11 02:34:47", - "globalTradeID": 419656926, - "orderNumber": 378681331722, - "rate": "0.01097903", - "total": "0.00000935", - "tradeID": 19495839, - "type": "sell" - }, - { - "amount": "0.00263502", - "date": "2019-06-11 02:34:44", - "globalTradeID": 419656922, - "orderNumber": 378681311742, - "rate": "0.01097902", - "total": "0.00002892", - "tradeID": 19495838, - "type": "sell" - }, - { - "amount": "0.00072603", - "date": "2019-06-11 02:33:09", - "globalTradeID": 419656903, - "orderNumber": 378680730324, - "rate": "0.01097738", - "total": "0.00000796", - "tradeID": 19495837, - "type": "sell" - }, - { - "amount": "3.81362404", - "date": "2019-06-11 02:31:53", - "globalTradeID": 419656875, - "orderNumber": 378680249805, - "rate": "0.01098999", - "total": "0.04191169", - "tradeID": 19495836, - "type": "buy" - }, - { - "amount": "3.51884830", - "date": "2019-06-11 02:31:36", - "globalTradeID": 419656867, - "orderNumber": 378680109945, - "rate": "0.01099140", - "total": "0.03867706", - "tradeID": 19495835, - "type": "sell" - }, - { - "amount": "0.00000181", - "date": "2019-06-11 02:31:32", - "globalTradeID": 419656866, - "orderNumber": 378680107947, - "rate": "0.01099141", - "total": "0.00000001", - "tradeID": 19495834, - "type": "buy" - }, - { - "amount": "1.19047895", - "date": "2019-06-11 02:31:13", - "globalTradeID": 419656858, - "orderNumber": 378680036019, - "rate": "0.01099140", - "total": "0.01308503", - "tradeID": 19495833, - "type": "sell" - }, - { - "amount": "0.09067275", - "date": "2019-06-11 02:31:11", - "globalTradeID": 419656857, - "orderNumber": 378680020035, - "rate": "0.01099140", - "total": "0.00099662", - "tradeID": 19495832, - "type": "sell" - }, - { - "amount": "0.20000000", - "date": "2019-06-11 02:30:30", - "globalTradeID": 419656847, - "orderNumber": 378679878177, - "rate": "0.01099140", - "total": "0.00219828", - "tradeID": 19495831, - "type": "buy" - }, - { - "amount": "0.00028223", - "date": "2019-06-11 02:29:54", - "globalTradeID": 419656831, - "orderNumber": 378679691364, - "rate": "0.01098366", - "total": "0.00000309", - "tradeID": 19495830, - "type": "sell" - }, - { - "amount": "14.18000000", - "date": "2019-06-11 02:26:56", - "globalTradeID": 419656743, - "orderNumber": 378678498558, - "rate": "0.01099141", - "total": "0.15585819", - "tradeID": 19495829, - "type": "buy" - }, - { - "amount": "6.67800000", - "date": "2019-06-11 02:26:55", - "globalTradeID": 419656741, - "orderNumber": 378678496560, - "rate": "0.01099141", - "total": "0.07340063", - "tradeID": 19495828, - "type": "buy" - }, - { - "amount": "9.80754099", - "date": "2019-06-11 02:26:55", - "globalTradeID": 419656738, - "orderNumber": 378678492564, - "rate": "0.01099141", - "total": "0.10779870", - "tradeID": 19495827, - "type": "buy" - }, - { - "amount": "0.10000000", - "date": "2019-06-11 02:26:55", - "globalTradeID": 419656737, - "orderNumber": 378678492564, - "rate": "0.01099100", - "total": "0.00109910", - "tradeID": 19495826, - "type": "buy" - }, - { - "amount": "0.58045901", - "date": "2019-06-11 02:26:55", - "globalTradeID": 419656736, - "orderNumber": 378678492564, - "rate": "0.01099100", - "total": "0.00637982", - "tradeID": 19495825, - "type": "buy" - }, - { - "amount": "0.97118176", - "date": "2019-06-11 02:25:28", - "globalTradeID": 419656692, - "orderNumber": 378677876181, - "rate": "0.01099141", - "total": "0.01067465", - "tradeID": 19495824, - "type": "buy" - }, - { - "amount": "1.21323848", - "date": "2019-06-11 02:25:22", - "globalTradeID": 419656686, - "orderNumber": 378677830227, - "rate": "0.01099141", - "total": "0.01333520", - "tradeID": 19495823, - "type": "buy" - }, - { - "amount": "0.61200000", - "date": "2019-06-11 02:25:10", - "globalTradeID": 419656674, - "orderNumber": 378677745312, - "rate": "0.01099141", - "total": "0.00672674", - "tradeID": 19495822, - "type": "buy" - }, - { - "amount": "4.42298415", - "date": "2019-06-11 02:25:10", - "globalTradeID": 419656673, - "orderNumber": 378677743314, - "rate": "0.01099141", - "total": "0.04861483", - "tradeID": 19495821, - "type": "buy" - }, - { - "amount": "0.32001585", - "date": "2019-06-11 02:25:10", - "globalTradeID": 419656672, - "orderNumber": 378677743314, - "rate": "0.01099140", - "total": "0.00351742", - "tradeID": 19495820, - "type": "buy" - }, - { - "amount": "0.09194560", - "date": "2019-06-11 02:23:58", - "globalTradeID": 419656622, - "orderNumber": 378677170887, - "rate": "0.01099139", - "total": "0.00101060", - "tradeID": 19495819, - "type": "buy" - }, - { - "amount": "0.89333991", - "date": "2019-06-11 02:22:33", - "globalTradeID": 419656536, - "orderNumber": 378676565493, - "rate": "0.01098805", - "total": "0.00981606", - "tradeID": 19495818, - "type": "buy" - }, - { - "amount": "3.46666009", - "date": "2019-06-11 02:22:33", - "globalTradeID": 419656535, - "orderNumber": 378676565493, - "rate": "0.01098804", - "total": "0.03809179", - "tradeID": 19495817, - "type": "buy" - }, - { - "amount": "2.83098726", - "date": "2019-06-11 02:21:53", - "globalTradeID": 419656510, - "orderNumber": 378676284774, - "rate": "0.01098616", - "total": "0.03110167", - "tradeID": 19495816, - "type": "buy" - }, - { - "amount": "9.88401274", - "date": "2019-06-11 02:21:53", - "globalTradeID": 419656509, - "orderNumber": 378676284774, - "rate": "0.01098615", - "total": "0.10858724", - "tradeID": 19495815, - "type": "buy" - }, - { - "amount": "2.51900000", - "date": "2019-06-11 02:21:52", - "globalTradeID": 419656507, - "orderNumber": 378676279779, - "rate": "0.01098615", - "total": "0.02767411", - "tradeID": 19495814, - "type": "buy" - }, - { - "amount": "6.19100000", - "date": "2019-06-11 02:21:52", - "globalTradeID": 419656505, - "orderNumber": 378676271787, - "rate": "0.01098615", - "total": "0.06801525", - "tradeID": 19495813, - "type": "buy" - }, - { - "amount": "1.80100000", - "date": "2019-06-11 02:21:52", - "globalTradeID": 419656504, - "orderNumber": 378676269789, - "rate": "0.01098615", - "total": "0.01978605", - "tradeID": 19495812, - "type": "buy" - }, - { - "amount": "10.26000000", - "date": "2019-06-11 02:21:52", - "globalTradeID": 419656503, - "orderNumber": 378676268790, - "rate": "0.01098615", - "total": "0.11271789", - "tradeID": 19495811, - "type": "buy" - }, - { - "amount": "1.98492975", - "date": "2019-06-11 02:21:51", - "globalTradeID": 419656502, - "orderNumber": 378676266792, - "rate": "0.01098615", - "total": "0.02180673", - "tradeID": 19495810, - "type": "buy" - }, - { - "amount": "0.22807025", - "date": "2019-06-11 02:21:51", - "globalTradeID": 419656501, - "orderNumber": 378676266792, - "rate": "0.01098614", - "total": "0.00250561", - "tradeID": 19495809, - "type": "buy" - }, - { - "amount": "8.26400000", - "date": "2019-06-11 02:21:51", - "globalTradeID": 419656499, - "orderNumber": 378676262796, - "rate": "0.01098615", - "total": "0.09078954", - "tradeID": 19495808, - "type": "buy" - }, - { - "amount": "3.63000000", - "date": "2019-06-11 02:21:51", - "globalTradeID": 419656496, - "orderNumber": 378676261797, - "rate": "0.01098615", - "total": "0.03987972", - "tradeID": 19495807, - "type": "buy" - }, - { - "amount": "5.82605751", - "date": "2019-06-11 02:21:46", - "globalTradeID": 419656491, - "orderNumber": 378676256802, - "rate": "0.01098615", - "total": "0.06400594", - "tradeID": 19495806, - "type": "buy" - }, - { - "amount": "5.82459583", - "date": "2019-06-11 02:21:46", - "globalTradeID": 419656488, - "orderNumber": 378676251807, - "rate": "0.01098616", - "total": "0.06398994", - "tradeID": 19495805, - "type": "buy" - }, - { - "amount": "5.82323047", - "date": "2019-06-11 02:21:46", - "globalTradeID": 419656478, - "orderNumber": 378676247811, - "rate": "0.01098617", - "total": "0.06397499", - "tradeID": 19495804, - "type": "buy" - }, - { - "amount": "0.00011303", - "date": "2019-06-11 02:17:12", - "globalTradeID": 419656401, - "orderNumber": 378674915145, - "rate": "0.01097003", - "total": "0.00000123", - "tradeID": 19495803, - "type": "sell" - }, - { - "amount": "0.00622868", - "date": "2019-06-11 02:15:35", - "globalTradeID": 419656344, - "orderNumber": 378674362698, - "rate": "0.01096700", - "total": "0.00006830", - "tradeID": 19495802, - "type": "sell" - }, - { - "amount": "6.44556753", - "date": "2019-06-11 02:14:58", - "globalTradeID": 419656335, - "orderNumber": 378674125935, - "rate": "0.01096644", - "total": "0.07068492", - "tradeID": 19495801, - "type": "sell" - }, - { - "amount": "0.00881642", - "date": "2019-06-11 02:13:59", - "globalTradeID": 419656229, - "orderNumber": 378673796265, - "rate": "0.01097611", - "total": "0.00009676", - "tradeID": 19495800, - "type": "sell" - }, - { - "amount": "4.34874974", - "date": "2019-06-11 02:11:11", - "globalTradeID": 419656134, - "orderNumber": 378672998064, - "rate": "0.01097600", - "total": "0.04773187", - "tradeID": 19495799, - "type": "sell" - }, - { - "amount": "0.12865121", - "date": "2019-06-11 02:11:11", - "globalTradeID": 419656133, - "orderNumber": 378672998064, - "rate": "0.01097601", - "total": "0.00141207", - "tradeID": 19495798, - "type": "sell" - }, - { - "amount": "1.32690213", - "date": "2019-06-11 02:11:11", - "globalTradeID": 419656132, - "orderNumber": 378672998064, - "rate": "0.01097601", - "total": "0.01456409", - "tradeID": 19495797, - "type": "sell" - }, - { - "amount": "4.08748000", - "date": "2019-06-11 02:11:11", - "globalTradeID": 419656131, - "orderNumber": 378672998064, - "rate": "0.01097632", - "total": "0.04486548", - "tradeID": 19495796, - "type": "sell" - }, - { - "amount": "0.00268670", - "date": "2019-06-11 02:10:51", - "globalTradeID": 419656071, - "orderNumber": 378672914148, - "rate": "0.01097629", - "total": "0.00002948", - "tradeID": 19495795, - "type": "sell" - }, - { - "amount": "0.00828786", - "date": "2019-06-11 02:10:50", - "globalTradeID": 419656068, - "orderNumber": 378672908154, - "rate": "0.01097629", - "total": "0.00009096", - "tradeID": 19495794, - "type": "sell" - }, - { - "amount": "0.00062589", - "date": "2019-06-11 02:09:13", - "globalTradeID": 419655987, - "orderNumber": 378672486576, - "rate": "0.01097625", - "total": "0.00000686", - "tradeID": 19495793, - "type": "sell" - }, - { - "amount": "0.08730618", - "date": "2019-06-11 02:07:30", - "globalTradeID": 419655936, - "orderNumber": 378671928135, - "rate": "0.01099588", - "total": "0.00096000", - "tradeID": 19495792, - "type": "buy" - }, - { - "amount": "2.94600000", - "date": "2019-06-11 02:07:27", - "globalTradeID": 419655935, - "orderNumber": 378671914149, - "rate": "0.01099590", - "total": "0.03239392", - "tradeID": 19495791, - "type": "buy" - }, - { - "amount": "18.99819158", - "date": "2019-06-11 02:07:23", - "globalTradeID": 419655932, - "orderNumber": 378671909154, - "rate": "0.01099590", - "total": "0.20890221", - "tradeID": 19495790, - "type": "buy" - }, - { - "amount": "8.49186817", - "date": "2019-06-11 02:07:23", - "globalTradeID": 419655931, - "orderNumber": 378671909154, - "rate": "0.01098289", - "total": "0.09326525", - "tradeID": 19495789, - "type": "buy" - }, - { - "amount": "0.92516246", - "date": "2019-06-11 02:07:23", - "globalTradeID": 419655930, - "orderNumber": 378671909154, - "rate": "0.01098289", - "total": "0.01016095", - "tradeID": 19495788, - "type": "buy" - }, - { - "amount": "40.55104177", - "date": "2019-06-11 02:05:51", - "globalTradeID": 419655888, - "orderNumber": 378671584479, - "rate": "0.01098982", - "total": "0.44564864", - "tradeID": 19495787, - "type": "buy" - }, - { - "amount": "0.00059948", - "date": "2019-06-11 02:04:30", - "globalTradeID": 419655839, - "orderNumber": 378671231832, - "rate": "0.01097601", - "total": "0.00000657", - "tradeID": 19495786, - "type": "sell" - }, - { - "amount": "0.00230684", - "date": "2019-06-11 02:04:29", - "globalTradeID": 419655835, - "orderNumber": 378671224839, - "rate": "0.01097601", - "total": "0.00002531", - "tradeID": 19495785, - "type": "sell" - }, - { - "amount": "0.00004919", - "date": "2019-06-11 02:02:52", - "globalTradeID": 419655760, - "orderNumber": 378670836228, - "rate": "0.01097624", - "total": "0.00000053", - "tradeID": 19495784, - "type": "sell" - }, - { - "amount": "0.00080537", - "date": "2019-06-11 02:02:50", - "globalTradeID": 419655755, - "orderNumber": 378670822242, - "rate": "0.01097624", - "total": "0.00000883", - "tradeID": 19495783, - "type": "sell" - }, - { - "amount": "0.14937440", - "date": "2019-06-11 02:01:24", - "globalTradeID": 419655714, - "orderNumber": 378670531533, - "rate": "0.01097609", - "total": "0.00163954", - "tradeID": 19495782, - "type": "sell" - }, - { - "amount": "0.11135441", - "date": "2019-06-11 02:01:18", - "globalTradeID": 419655711, - "orderNumber": 378670504560, - "rate": "0.01097610", - "total": "0.00122223", - "tradeID": 19495781, - "type": "sell" - }, - { - "amount": "0.00214374", - "date": "2019-06-11 02:01:12", - "globalTradeID": 419655698, - "orderNumber": 378670483581, - "rate": "0.01097610", - "total": "0.00002352", - "tradeID": 19495780, - "type": "sell" - }, - { - "amount": "0.00071883", - "date": "2019-06-11 02:01:11", - "globalTradeID": 419655693, - "orderNumber": 378670480584, - "rate": "0.01097610", - "total": "0.00000788", - "tradeID": 19495779, - "type": "sell" - }, - { - "amount": "0.09090000", - "date": "2019-06-11 02:01:10", - "globalTradeID": 419655690, - "orderNumber": 378670475589, - "rate": "0.01098999", - "total": "0.00099899", - "tradeID": 19495778, - "type": "buy" - }, - { - "amount": "0.10000000", - "date": "2019-06-11 02:00:41", - "globalTradeID": 419655677, - "orderNumber": 378670377687, - "rate": "0.01098998", - "total": "0.00109899", - "tradeID": 19495777, - "type": "buy" - }, - { - "amount": "22.47015128", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655660, - "orderNumber": 378670228836, - "rate": "0.01098999", - "total": "0.24694673", - "tradeID": 19495776, - "type": "buy" - }, - { - "amount": "0.15373084", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655659, - "orderNumber": 378670228836, - "rate": "0.01098642", - "total": "0.00168895", - "tradeID": 19495775, - "type": "buy" - }, - { - "amount": "0.00928634", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655658, - "orderNumber": 378670228836, - "rate": "0.01098400", - "total": "0.00010200", - "tradeID": 19495774, - "type": "buy" - }, - { - "amount": "0.05936375", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655657, - "orderNumber": 378670228836, - "rate": "0.01098025", - "total": "0.00065182", - "tradeID": 19495773, - "type": "buy" - }, - { - "amount": "0.02000000", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655656, - "orderNumber": 378670228836, - "rate": "0.01098000", - "total": "0.00021960", - "tradeID": 19495772, - "type": "buy" - }, - { - "amount": "0.00981951", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655655, - "orderNumber": 378670228836, - "rate": "0.01098000", - "total": "0.00010781", - "tradeID": 19495771, - "type": "buy" - }, - { - "amount": "0.00912443", - "date": "2019-06-11 01:59:51", - "globalTradeID": 419655652, - "orderNumber": 378670225839, - "rate": "0.01097603", - "total": "0.00010015", - "tradeID": 19495770, - "type": "sell" - }, - { - "amount": "0.00028061", - "date": "2019-06-11 01:59:35", - "globalTradeID": 419655640, - "orderNumber": 378670189875, - "rate": "0.01097606", - "total": "0.00000307", - "tradeID": 19495769, - "type": "sell" - }, - { - "amount": "1.29702296", - "date": "2019-06-11 01:59:23", - "globalTradeID": 419655633, - "orderNumber": 378670155909, - "rate": "0.01098000", - "total": "0.01424131", - "tradeID": 19495768, - "type": "buy" - }, - { - "amount": "1.18408220", - "date": "2019-06-11 01:59:05", - "globalTradeID": 419655630, - "orderNumber": 378670101963, - "rate": "0.01098000", - "total": "0.01300122", - "tradeID": 19495767, - "type": "buy" - }, - { - "amount": "0.02045548", - "date": "2019-06-11 01:58:00", - "globalTradeID": 419655590, - "orderNumber": 378669894171, - "rate": "0.01097603", - "total": "0.00022451", - "tradeID": 19495766, - "type": "sell" - }, - { - "amount": "0.01740344", - "date": "2019-06-11 01:58:00", - "globalTradeID": 419655589, - "orderNumber": 378669894171, - "rate": "0.01097605", - "total": "0.00019102", - "tradeID": 19495765, - "type": "sell" - }, - { - "amount": "0.00259656", - "date": "2019-06-11 01:58:00", - "globalTradeID": 419655588, - "orderNumber": 378669890175, - "rate": "0.01097605", - "total": "0.00002849", - "tradeID": 19495764, - "type": "sell" - }, - { - "amount": "2.29560855", - "date": "2019-06-11 01:57:42", - "globalTradeID": 419655571, - "orderNumber": 378669825240, - "rate": "0.01097605", - "total": "0.02519671", - "tradeID": 19495763, - "type": "sell" - }, - { - "amount": "8.67379891", - "date": "2019-06-11 01:57:06", - "globalTradeID": 419655547, - "orderNumber": 378669717348, - "rate": "0.01098000", - "total": "0.09523831", - "tradeID": 19495762, - "type": "buy" - }, - { - "amount": "0.00017674", - "date": "2019-06-11 01:56:19", - "globalTradeID": 419655520, - "orderNumber": 378669567498, - "rate": "0.01097606", - "total": "0.00000193", - "tradeID": 19495761, - "type": "sell" - }, - { - "amount": "0.00047831", - "date": "2019-06-11 01:53:01", - "globalTradeID": 419655454, - "orderNumber": 378668865201, - "rate": "0.01097600", - "total": "0.00000524", - "tradeID": 19495760, - "type": "sell" - }, - { - "amount": "0.00133017", - "date": "2019-06-11 01:52:57", - "globalTradeID": 419655453, - "orderNumber": 378668862204, - "rate": "0.01097600", - "total": "0.00001459", - "tradeID": 19495759, - "type": "sell" - }, - { - "amount": "0.01109161", - "date": "2019-06-11 01:50:44", - "globalTradeID": 419655381, - "orderNumber": 378668335731, - "rate": "0.01097600", - "total": "0.00012174", - "tradeID": 19495758, - "type": "sell" - }, - { - "amount": "0.01028779", - "date": "2019-06-11 01:50:41", - "globalTradeID": 419655380, - "orderNumber": 378668318748, - "rate": "0.01098000", - "total": "0.00011295", - "tradeID": 19495757, - "type": "buy" - }, - { - "amount": "0.00912435", - "date": "2019-06-11 01:49:39", - "globalTradeID": 419655343, - "orderNumber": 378668097969, - "rate": "0.01097613", - "total": "0.00010015", - "tradeID": 19495756, - "type": "sell" - }, - { - "amount": "17.58144635", - "date": "2019-06-11 01:49:38", - "globalTradeID": 419655339, - "orderNumber": 378668091975, - "rate": "0.01098000", - "total": "0.19304428", - "tradeID": 19495755, - "type": "buy" - }, - { - "amount": "0.06014124", - "date": "2019-06-11 01:48:21", - "globalTradeID": 419655307, - "orderNumber": 378667813254, - "rate": "0.01097631", - "total": "0.00066012", - "tradeID": 19495754, - "type": "sell" - }, - { - "amount": "0.00205442", - "date": "2019-06-11 01:48:15", - "globalTradeID": 419655303, - "orderNumber": 378667800267, - "rate": "0.01097631", - "total": "0.00002254", - "tradeID": 19495753, - "type": "sell" - } - ], - "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR", - "bodyParams": "", - "headers": {} - }, { "data": { "1CR": { @@ -8948,6 +6941,2787 @@ "queryString": "command=returnChartData\u0026currencyPair=BTC_XMR\u0026end=1405699400\u0026period=300\u0026start=1405699200", "bodyParams": "", "headers": {} + }, + { + "data": [ + { + "amount": "1.01999999", + "date": "2020-09-14 04:24:31", + "globalTradeID": 487261525, + "orderNumber": 494135055429, + "rate": "0.00822633", + "total": "0.00839085", + "tradeID": 20587658, + "type": "sell" + }, + { + "amount": "0.95899999", + "date": "2020-09-14 04:24:31", + "globalTradeID": 487261524, + "orderNumber": 494135048436, + "rate": "0.00823403", + "total": "0.00789643", + "tradeID": 20587657, + "type": "sell" + }, + { + "amount": "3.46500000", + "date": "2020-09-14 04:24:26", + "globalTradeID": 487261522, + "orderNumber": 494134978506, + "rate": "0.00824518", + "total": "0.02856954", + "tradeID": 20587656, + "type": "buy" + }, + { + "amount": "3.89229925", + "date": "2020-09-14 04:24:26", + "globalTradeID": 487261521, + "orderNumber": 494134978506, + "rate": "0.00824000", + "total": "0.03207254", + "tradeID": 20587655, + "type": "buy" + }, + { + "amount": "1.11909806", + "date": "2020-09-14 04:24:25", + "globalTradeID": 487261517, + "orderNumber": 494134956528, + "rate": "0.00824000", + "total": "0.00922136", + "tradeID": 20587654, + "type": "buy" + }, + { + "amount": "0.89223049", + "date": "2020-09-14 04:24:25", + "globalTradeID": 487261516, + "orderNumber": 494134956528, + "rate": "0.00823794", + "total": "0.00735014", + "tradeID": 20587653, + "type": "buy" + }, + { + "amount": "0.80540269", + "date": "2020-09-14 04:24:24", + "globalTradeID": 487261503, + "orderNumber": 494134927557, + "rate": "0.00824000", + "total": "0.00663651", + "tradeID": 20587652, + "type": "buy" + }, + { + "amount": "12.00000000", + "date": "2020-09-14 04:24:24", + "globalTradeID": 487261501, + "orderNumber": 494134919565, + "rate": "0.00820175", + "total": "0.09842100", + "tradeID": 20587651, + "type": "buy" + }, + { + "amount": "0.59764984", + "date": "2020-09-14 04:24:24", + "globalTradeID": 487261500, + "orderNumber": 494134916568, + "rate": "0.00820175", + "total": "0.00490177", + "tradeID": 20587650, + "type": "buy" + }, + { + "amount": "2.27774282", + "date": "2020-09-14 04:24:23", + "globalTradeID": 487261499, + "orderNumber": 494134912572, + "rate": "0.00820175", + "total": "0.01868147", + "tradeID": 20587649, + "type": "buy" + }, + { + "amount": "1.00199293", + "date": "2020-09-14 04:24:23", + "globalTradeID": 487261498, + "orderNumber": 494134908576, + "rate": "0.00820175", + "total": "0.00821809", + "tradeID": 20587648, + "type": "buy" + }, + { + "amount": "1.98926043", + "date": "2020-09-14 04:24:23", + "globalTradeID": 487261496, + "orderNumber": 494134900584, + "rate": "0.00820091", + "total": "0.01631374", + "tradeID": 20587647, + "type": "buy" + }, + { + "amount": "1.16419284", + "date": "2020-09-14 04:24:23", + "globalTradeID": 487261495, + "orderNumber": 494134900584, + "rate": "0.00820090", + "total": "0.00954742", + "tradeID": 20587646, + "type": "buy" + }, + { + "amount": "1.20504315", + "date": "2020-09-14 04:24:23", + "globalTradeID": 487261492, + "orderNumber": 494134897587, + "rate": "0.00820089", + "total": "0.00988242", + "tradeID": 20587645, + "type": "buy" + }, + { + "amount": "0.59942757", + "date": "2020-09-14 04:24:20", + "globalTradeID": 487261484, + "orderNumber": 494134881603, + "rate": "0.00819999", + "total": "0.00491530", + "tradeID": 20587644, + "type": "sell" + }, + { + "amount": "0.10325487", + "date": "2020-09-14 04:24:20", + "globalTradeID": 487261483, + "orderNumber": 494134881603, + "rate": "0.00820000", + "total": "0.00084668", + "tradeID": 20587643, + "type": "sell" + }, + { + "amount": "2.78010353", + "date": "2020-09-14 04:24:20", + "globalTradeID": 487261482, + "orderNumber": 494134881603, + "rate": "0.00820000", + "total": "0.02279684", + "tradeID": 20587642, + "type": "sell" + }, + { + "amount": "0.59942757", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261479, + "orderNumber": 494134878606, + "rate": "0.00820000", + "total": "0.00491530", + "tradeID": 20587641, + "type": "sell" + }, + { + "amount": "0.03959144", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261478, + "orderNumber": 494134877607, + "rate": "0.00820095", + "total": "0.00032468", + "tradeID": 20587640, + "type": "buy" + }, + { + "amount": "12.30706402", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261477, + "orderNumber": 494134875609, + "rate": "0.00820000", + "total": "0.10091792", + "tradeID": 20587639, + "type": "sell" + }, + { + "amount": "23.30241831", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261476, + "orderNumber": 494134875609, + "rate": "0.00820000", + "total": "0.19107983", + "tradeID": 20587638, + "type": "sell" + }, + { + "amount": "1.69758169", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261475, + "orderNumber": 494134872612, + "rate": "0.00820000", + "total": "0.01392016", + "tradeID": 20587637, + "type": "sell" + }, + { + "amount": "0.01571831", + "date": "2020-09-14 04:24:19", + "globalTradeID": 487261474, + "orderNumber": 494134872612, + "rate": "0.00820000", + "total": "0.00012889", + "tradeID": 20587636, + "type": "sell" + }, + { + "amount": "0.00428169", + "date": "2020-09-14 04:24:18", + "globalTradeID": 487261473, + "orderNumber": 494134867617, + "rate": "0.00820000", + "total": "0.00003510", + "tradeID": 20587635, + "type": "sell" + }, + { + "amount": "0.02021830", + "date": "2020-09-14 04:24:18", + "globalTradeID": 487261472, + "orderNumber": 494134867617, + "rate": "0.00820000", + "total": "0.00016579", + "tradeID": 20587634, + "type": "sell" + }, + { + "amount": "0.25000000", + "date": "2020-09-14 04:24:18", + "globalTradeID": 487261471, + "orderNumber": 494134867617, + "rate": "0.00820000", + "total": "0.00205000", + "tradeID": 20587633, + "type": "sell" + }, + { + "amount": "0.03245364", + "date": "2020-09-14 04:24:17", + "globalTradeID": 487261468, + "orderNumber": 494134839645, + "rate": "0.00820135", + "total": "0.00026616", + "tradeID": 20587632, + "type": "sell" + }, + { + "amount": "0.00557834", + "date": "2020-09-14 04:24:01", + "globalTradeID": 487261438, + "orderNumber": 494134799685, + "rate": "0.00820135", + "total": "0.00004574", + "tradeID": 20587631, + "type": "sell" + }, + { + "amount": "0.00000242", + "date": "2020-09-14 04:24:01", + "globalTradeID": 487261434, + "orderNumber": 494134797687, + "rate": "0.00821133", + "total": "0.00000001", + "tradeID": 20587630, + "type": "buy" + }, + { + "amount": "0.00071451", + "date": "2020-09-14 04:22:25", + "globalTradeID": 487261288, + "orderNumber": 494134544940, + "rate": "0.00820135", + "total": "0.00000585", + "tradeID": 20587629, + "type": "sell" + }, + { + "amount": "0.00007557", + "date": "2020-09-14 04:20:10", + "globalTradeID": 487261073, + "orderNumber": 494134160325, + "rate": "0.00820382", + "total": "0.00000061", + "tradeID": 20587628, + "type": "sell" + }, + { + "amount": "0.00012557", + "date": "2020-09-14 04:18:31", + "globalTradeID": 487260901, + "orderNumber": 494133954531, + "rate": "0.00820240", + "total": "0.00000102", + "tradeID": 20587627, + "type": "sell" + }, + { + "amount": "0.00000242", + "date": "2020-09-14 04:18:30", + "globalTradeID": 487260900, + "orderNumber": 494133952533, + "rate": "0.00821499", + "total": "0.00000001", + "tradeID": 20587626, + "type": "buy" + }, + { + "amount": "0.04723429", + "date": "2020-09-14 04:17:30", + "globalTradeID": 487260836, + "orderNumber": 494133812673, + "rate": "0.00821474", + "total": "0.00038801", + "tradeID": 20587625, + "type": "buy" + }, + { + "amount": "0.14616250", + "date": "2020-09-14 04:14:38", + "globalTradeID": 487260577, + "orderNumber": 494133368118, + "rate": "0.00821004", + "total": "0.00119999", + "tradeID": 20587624, + "type": "buy" + }, + { + "amount": "0.00009510", + "date": "2020-09-14 04:13:27", + "globalTradeID": 487260477, + "orderNumber": 494133230256, + "rate": "0.00820136", + "total": "0.00000077", + "tradeID": 20587623, + "type": "sell" + }, + { + "amount": "0.00000511", + "date": "2020-09-14 04:13:27", + "globalTradeID": 487260475, + "orderNumber": 494133225261, + "rate": "0.00820999", + "total": "0.00000004", + "tradeID": 20587622, + "type": "buy" + }, + { + "amount": "0.00033531", + "date": "2020-09-14 04:13:20", + "globalTradeID": 487260457, + "orderNumber": 494133210276, + "rate": "0.00820135", + "total": "0.00000274", + "tradeID": 20587621, + "type": "sell" + }, + { + "amount": "0.00009510", + "date": "2020-09-14 04:13:20", + "globalTradeID": 487260455, + "orderNumber": 494133209277, + "rate": "0.00820135", + "total": "0.00000077", + "tradeID": 20587620, + "type": "sell" + }, + { + "amount": "0.01079942", + "date": "2020-09-14 04:11:42", + "globalTradeID": 487260303, + "orderNumber": 494133009477, + "rate": "0.00820136", + "total": "0.00008856", + "tradeID": 20587619, + "type": "sell" + }, + { + "amount": "0.00095350", + "date": "2020-09-14 04:11:42", + "globalTradeID": 487260301, + "orderNumber": 494133008478, + "rate": "0.00820136", + "total": "0.00000781", + "tradeID": 20587618, + "type": "sell" + }, + { + "amount": "0.00000397", + "date": "2020-09-14 04:07:46", + "globalTradeID": 487259946, + "orderNumber": 494132521965, + "rate": "0.00821499", + "total": "0.00000003", + "tradeID": 20587617, + "type": "buy" + }, + { + "amount": "0.32365772", + "date": "2020-09-14 04:06:26", + "globalTradeID": 487259836, + "orderNumber": 494132371116, + "rate": "0.00820999", + "total": "0.00265722", + "tradeID": 20587616, + "type": "buy" + }, + { + "amount": "0.14714971", + "date": "2020-09-14 04:05:45", + "globalTradeID": 487259781, + "orderNumber": 494132270217, + "rate": "0.00820154", + "total": "0.00120685", + "tradeID": 20587615, + "type": "sell" + }, + { + "amount": "0.03342502", + "date": "2020-09-14 04:05:13", + "globalTradeID": 487259720, + "orderNumber": 494132203284, + "rate": "0.00821041", + "total": "0.00027443", + "tradeID": 20587614, + "type": "sell" + }, + { + "amount": "0.00004141", + "date": "2020-09-14 04:04:57", + "globalTradeID": 487259692, + "orderNumber": 494132164323, + "rate": "0.00821041", + "total": "0.00000033", + "tradeID": 20587613, + "type": "sell" + }, + { + "amount": "0.00015955", + "date": "2020-09-14 04:04:56", + "globalTradeID": 487259690, + "orderNumber": 494132161326, + "rate": "0.00821041", + "total": "0.00000130", + "tradeID": 20587612, + "type": "sell" + }, + { + "amount": "0.14610484", + "date": "2020-09-14 04:04:32", + "globalTradeID": 487259643, + "orderNumber": 494132113374, + "rate": "0.00821324", + "total": "0.00119999", + "tradeID": 20587611, + "type": "buy" + }, + { + "amount": "0.00076122", + "date": "2020-09-14 04:03:20", + "globalTradeID": 487259471, + "orderNumber": 494131945542, + "rate": "0.00821041", + "total": "0.00000624", + "tradeID": 20587610, + "type": "sell" + }, + { + "amount": "0.00009987", + "date": "2020-09-14 04:03:16", + "globalTradeID": 487259450, + "orderNumber": 494131930557, + "rate": "0.00821041", + "total": "0.00000081", + "tradeID": 20587609, + "type": "sell" + }, + { + "amount": "0.00011083", + "date": "2020-09-14 04:03:16", + "globalTradeID": 487259449, + "orderNumber": 494131928559, + "rate": "0.00821041", + "total": "0.00000090", + "tradeID": 20587608, + "type": "sell" + }, + { + "amount": "0.03501662", + "date": "2020-09-14 03:59:46", + "globalTradeID": 487259059, + "orderNumber": 494131548939, + "rate": "0.00821578", + "total": "0.00028768", + "tradeID": 20587607, + "type": "sell" + }, + { + "amount": "0.00000321", + "date": "2020-09-14 03:57:48", + "globalTradeID": 487258848, + "orderNumber": 494131335153, + "rate": "0.00822999", + "total": "0.00000002", + "tradeID": 20587606, + "type": "buy" + }, + { + "amount": "0.00043942", + "date": "2020-09-14 03:57:43", + "globalTradeID": 487258837, + "orderNumber": 494131324164, + "rate": "0.00821530", + "total": "0.00000360", + "tradeID": 20587605, + "type": "sell" + }, + { + "amount": "0.00011443", + "date": "2020-09-14 03:54:52", + "globalTradeID": 487258479, + "orderNumber": 494131023465, + "rate": "0.00821401", + "total": "0.00000093", + "tradeID": 20587604, + "type": "sell" + }, + { + "amount": "0.00000242", + "date": "2020-09-14 03:53:13", + "globalTradeID": 487258254, + "orderNumber": 494130788700, + "rate": "0.00822499", + "total": "0.00000001", + "tradeID": 20587603, + "type": "buy" + }, + { + "amount": "0.00037139", + "date": "2020-09-14 03:53:12", + "globalTradeID": 487258248, + "orderNumber": 494130785703, + "rate": "0.00821224", + "total": "0.00000304", + "tradeID": 20587602, + "type": "sell" + }, + { + "amount": "0.00025693", + "date": "2020-09-14 03:53:10", + "globalTradeID": 487258243, + "orderNumber": 494130782706, + "rate": "0.00821222", + "total": "0.00000210", + "tradeID": 20587601, + "type": "sell" + }, + { + "amount": "0.45807549", + "date": "2020-09-14 03:52:03", + "globalTradeID": 487258087, + "orderNumber": 494130620868, + "rate": "0.00822500", + "total": "0.00376767", + "tradeID": 20587600, + "type": "buy" + }, + { + "amount": "0.00000243", + "date": "2020-09-14 03:50:18", + "globalTradeID": 487257904, + "orderNumber": 494130421068, + "rate": "0.00821041", + "total": "0.00000001", + "tradeID": 20587599, + "type": "sell" + }, + { + "amount": "0.00011672", + "date": "2020-09-14 03:50:15", + "globalTradeID": 487257891, + "orderNumber": 494130410079, + "rate": "0.00821983", + "total": "0.00000095", + "tradeID": 20587598, + "type": "buy" + }, + { + "amount": "0.00028987", + "date": "2020-09-14 03:50:13", + "globalTradeID": 487257888, + "orderNumber": 494130407082, + "rate": "0.00821042", + "total": "0.00000237", + "tradeID": 20587597, + "type": "sell" + }, + { + "amount": "0.00054808", + "date": "2020-09-14 03:50:10", + "globalTradeID": 487257876, + "orderNumber": 494130397092, + "rate": "0.00821042", + "total": "0.00000449", + "tradeID": 20587596, + "type": "sell" + }, + { + "amount": "0.00010902", + "date": "2020-09-14 03:48:28", + "globalTradeID": 487257711, + "orderNumber": 494130200289, + "rate": "0.00821825", + "total": "0.00000089", + "tradeID": 20587595, + "type": "buy" + }, + { + "amount": "0.00150418", + "date": "2020-09-14 03:48:27", + "globalTradeID": 487257704, + "orderNumber": 494130194295, + "rate": "0.00821042", + "total": "0.00001234", + "tradeID": 20587594, + "type": "sell" + }, + { + "amount": "0.00038731", + "date": "2020-09-14 03:48:25", + "globalTradeID": 487257700, + "orderNumber": 494130188301, + "rate": "0.00821042", + "total": "0.00000317", + "tradeID": 20587593, + "type": "sell" + }, + { + "amount": "0.00001612", + "date": "2020-09-14 03:45:26", + "globalTradeID": 487257387, + "orderNumber": 494129770719, + "rate": "0.00821999", + "total": "0.00000013", + "tradeID": 20587592, + "type": "buy" + }, + { + "amount": "0.00014859", + "date": "2020-09-14 03:45:25", + "globalTradeID": 487257386, + "orderNumber": 494129769720, + "rate": "0.00821051", + "total": "0.00000121", + "tradeID": 20587591, + "type": "sell" + }, + { + "amount": "0.00003653", + "date": "2020-09-14 03:45:24", + "globalTradeID": 487257383, + "orderNumber": 494129768721, + "rate": "0.00821051", + "total": "0.00000029", + "tradeID": 20587590, + "type": "sell" + }, + { + "amount": "0.00011448", + "date": "2020-09-14 03:45:23", + "globalTradeID": 487257381, + "orderNumber": 494129767722, + "rate": "0.00821051", + "total": "0.00000093", + "tradeID": 20587589, + "type": "sell" + }, + { + "amount": "0.14593977", + "date": "2020-09-14 03:44:37", + "globalTradeID": 487257301, + "orderNumber": 494129676813, + "rate": "0.00822188", + "total": "0.00119989", + "tradeID": 20587588, + "type": "buy" + }, + { + "amount": "0.00000456", + "date": "2020-09-14 03:43:41", + "globalTradeID": 487257187, + "orderNumber": 494129576913, + "rate": "0.00821999", + "total": "0.00000003", + "tradeID": 20587587, + "type": "buy" + }, + { + "amount": "0.00070763", + "date": "2020-09-14 03:43:39", + "globalTradeID": 487257181, + "orderNumber": 494129572917, + "rate": "0.00821042", + "total": "0.00000580", + "tradeID": 20587586, + "type": "sell" + }, + { + "amount": "0.00000491", + "date": "2020-09-14 03:42:03", + "globalTradeID": 487257017, + "orderNumber": 494129394096, + "rate": "0.00821992", + "total": "0.00000004", + "tradeID": 20587585, + "type": "buy" + }, + { + "amount": "0.00001922", + "date": "2020-09-14 03:40:51", + "globalTradeID": 487256887, + "orderNumber": 494129239251, + "rate": "0.00822756", + "total": "0.00000015", + "tradeID": 20587584, + "type": "buy" + }, + { + "amount": "0.00045280", + "date": "2020-09-14 03:40:50", + "globalTradeID": 487256882, + "orderNumber": 494129236254, + "rate": "0.00821542", + "total": "0.00000371", + "tradeID": 20587583, + "type": "sell" + }, + { + "amount": "0.00003164", + "date": "2020-09-14 03:40:46", + "globalTradeID": 487256869, + "orderNumber": 494129228262, + "rate": "0.00821535", + "total": "0.00000025", + "tradeID": 20587582, + "type": "sell" + }, + { + "amount": "0.00039933", + "date": "2020-09-14 03:39:05", + "globalTradeID": 487256647, + "orderNumber": 494129011479, + "rate": "0.00821356", + "total": "0.00000327", + "tradeID": 20587581, + "type": "sell" + }, + { + "amount": "0.00005323", + "date": "2020-09-14 03:37:55", + "globalTradeID": 487256501, + "orderNumber": 494128861629, + "rate": "0.00822499", + "total": "0.00000043", + "tradeID": 20587580, + "type": "buy" + }, + { + "amount": "1.15100000", + "date": "2020-09-14 03:37:22", + "globalTradeID": 487256434, + "orderNumber": 494128800690, + "rate": "0.00821167", + "total": "0.00945163", + "tradeID": 20587579, + "type": "sell" + }, + { + "amount": "8.42586659", + "date": "2020-09-14 03:35:12", + "globalTradeID": 487256160, + "orderNumber": 494128592898, + "rate": "0.00821999", + "total": "0.06926053", + "tradeID": 20587578, + "type": "buy" + }, + { + "amount": "0.00037878", + "date": "2020-09-14 03:35:03", + "globalTradeID": 487256145, + "orderNumber": 494128587903, + "rate": "0.00821044", + "total": "0.00000310", + "tradeID": 20587577, + "type": "sell" + }, + { + "amount": "0.00000802", + "date": "2020-09-14 03:35:03", + "globalTradeID": 487256144, + "orderNumber": 494128585905, + "rate": "0.00821999", + "total": "0.00000006", + "tradeID": 20587576, + "type": "buy" + }, + { + "amount": "0.00152732", + "date": "2020-09-14 03:34:59", + "globalTradeID": 487256134, + "orderNumber": 494128584906, + "rate": "0.00821044", + "total": "0.00001253", + "tradeID": 20587575, + "type": "sell" + }, + { + "amount": "0.00031058", + "date": "2020-09-14 03:33:19", + "globalTradeID": 487255918, + "orderNumber": 494128426065, + "rate": "0.00821041", + "total": "0.00000254", + "tradeID": 20587574, + "type": "sell" + }, + { + "amount": "0.00012301", + "date": "2020-09-14 03:33:18", + "globalTradeID": 487255917, + "orderNumber": 494128425066, + "rate": "0.00821041", + "total": "0.00000100", + "tradeID": 20587573, + "type": "sell" + }, + { + "amount": "0.00001831", + "date": "2020-09-14 03:32:08", + "globalTradeID": 487255788, + "orderNumber": 494128362129, + "rate": "0.00822497", + "total": "0.00000015", + "tradeID": 20587572, + "type": "buy" + }, + { + "amount": "0.00035806", + "date": "2020-09-14 03:32:02", + "globalTradeID": 487255766, + "orderNumber": 494128361130, + "rate": "0.00821088", + "total": "0.00000293", + "tradeID": 20587571, + "type": "sell" + }, + { + "amount": "0.00007794", + "date": "2020-09-14 03:32:01", + "globalTradeID": 487255765, + "orderNumber": 494128360131, + "rate": "0.00821088", + "total": "0.00000063", + "tradeID": 20587570, + "type": "sell" + }, + { + "amount": "5.82880000", + "date": "2020-09-14 03:29:37", + "globalTradeID": 487255576, + "orderNumber": 494128136355, + "rate": "0.00821500", + "total": "0.04788359", + "tradeID": 20587569, + "type": "buy" + }, + { + "amount": "0.00000659", + "date": "2020-09-14 03:29:04", + "globalTradeID": 487255520, + "orderNumber": 494128115376, + "rate": "0.00821499", + "total": "0.00000005", + "tradeID": 20587568, + "type": "buy" + }, + { + "amount": "0.00018147", + "date": "2020-09-14 03:29:02", + "globalTradeID": 487255514, + "orderNumber": 494128111380, + "rate": "0.00821042", + "total": "0.00000148", + "tradeID": 20587567, + "type": "sell" + }, + { + "amount": "0.00017416", + "date": "2020-09-14 03:28:56", + "globalTradeID": 487255501, + "orderNumber": 494128101390, + "rate": "0.00821042", + "total": "0.00000142", + "tradeID": 20587566, + "type": "sell" + }, + { + "amount": "0.00005792", + "date": "2020-09-14 03:26:11", + "globalTradeID": 487255266, + "orderNumber": 494128010481, + "rate": "0.00821499", + "total": "0.00000047", + "tradeID": 20587565, + "type": "buy" + }, + { + "amount": "0.00064917", + "date": "2020-09-14 03:26:10", + "globalTradeID": 487255262, + "orderNumber": 494128009482, + "rate": "0.00821042", + "total": "0.00000532", + "tradeID": 20587564, + "type": "sell" + }, + { + "amount": "0.00290362", + "date": "2020-09-14 03:26:06", + "globalTradeID": 487255255, + "orderNumber": 494128008483, + "rate": "0.00821042", + "total": "0.00002383", + "tradeID": 20587563, + "type": "sell" + }, + { + "amount": "0.00014128", + "date": "2020-09-14 03:26:03", + "globalTradeID": 487255249, + "orderNumber": 494128003488, + "rate": "0.00821042", + "total": "0.00000115", + "tradeID": 20587562, + "type": "sell" + }, + { + "amount": "0.14571949", + "date": "2020-09-14 03:24:52", + "globalTradeID": 487255107, + "orderNumber": 494127865626, + "rate": "0.00823500", + "total": "0.00120000", + "tradeID": 20587561, + "type": "buy" + }, + { + "amount": "0.49743290", + "date": "2020-09-14 03:24:22", + "globalTradeID": 487255066, + "orderNumber": 494127813678, + "rate": "0.00823499", + "total": "0.00409635", + "tradeID": 20587560, + "type": "buy" + }, + { + "amount": "0.00010814", + "date": "2020-09-14 03:23:13", + "globalTradeID": 487254928, + "orderNumber": 494127745746, + "rate": "0.00823001", + "total": "0.00000088", + "tradeID": 20587559, + "type": "sell" + }, + { + "amount": "0.00163912", + "date": "2020-09-14 03:23:09", + "globalTradeID": 487254920, + "orderNumber": 494127735756, + "rate": "0.00823001", + "total": "0.00001348", + "tradeID": 20587558, + "type": "sell" + }, + { + "amount": "0.00054191", + "date": "2020-09-14 03:23:07", + "globalTradeID": 487254918, + "orderNumber": 494127733758, + "rate": "0.00823001", + "total": "0.00000445", + "tradeID": 20587557, + "type": "sell" + }, + { + "amount": "0.00006318", + "date": "2020-09-14 03:23:07", + "globalTradeID": 487254917, + "orderNumber": 494127732759, + "rate": "0.00823001", + "total": "0.00000051", + "tradeID": 20587556, + "type": "sell" + }, + { + "amount": "0.00069501", + "date": "2020-09-14 03:23:07", + "globalTradeID": 487254916, + "orderNumber": 494127731760, + "rate": "0.00823001", + "total": "0.00000571", + "tradeID": 20587555, + "type": "sell" + }, + { + "amount": "0.00000242", + "date": "2020-09-14 03:20:12", + "globalTradeID": 487254666, + "orderNumber": 494127468024, + "rate": "0.00822999", + "total": "0.00000001", + "tradeID": 20587554, + "type": "buy" + }, + { + "amount": "0.00015328", + "date": "2020-09-14 03:20:11", + "globalTradeID": 487254663, + "orderNumber": 494127466026, + "rate": "0.00822004", + "total": "0.00000125", + "tradeID": 20587553, + "type": "sell" + }, + { + "amount": "0.00039294", + "date": "2020-09-14 03:20:08", + "globalTradeID": 487254657, + "orderNumber": 494127458034, + "rate": "0.00822003", + "total": "0.00000322", + "tradeID": 20587552, + "type": "sell" + }, + { + "amount": "0.00015814", + "date": "2020-09-14 03:20:05", + "globalTradeID": 487254650, + "orderNumber": 494127447045, + "rate": "0.00822013", + "total": "0.00000129", + "tradeID": 20587551, + "type": "sell" + }, + { + "amount": "0.14580820", + "date": "2020-09-14 03:14:51", + "globalTradeID": 487254205, + "orderNumber": 494126973519, + "rate": "0.00822999", + "total": "0.00120000", + "tradeID": 20587550, + "type": "buy" + }, + { + "amount": "0.00002919", + "date": "2020-09-14 03:14:28", + "globalTradeID": 487254166, + "orderNumber": 494126967525, + "rate": "0.00822000", + "total": "0.00000023", + "tradeID": 20587549, + "type": "sell" + }, + { + "amount": "0.00066301", + "date": "2020-09-14 03:14:27", + "globalTradeID": 487254165, + "orderNumber": 494126966526, + "rate": "0.00822000", + "total": "0.00000544", + "tradeID": 20587548, + "type": "sell" + }, + { + "amount": "0.01344092", + "date": "2020-09-14 03:10:33", + "globalTradeID": 487253810, + "orderNumber": 494126415078, + "rate": "0.00823009", + "total": "0.00011061", + "tradeID": 20587547, + "type": "sell" + }, + { + "amount": "0.00249150", + "date": "2020-09-14 03:06:39", + "globalTradeID": 487253420, + "orderNumber": 494126050443, + "rate": "0.00824001", + "total": "0.00002052", + "tradeID": 20587546, + "type": "sell" + }, + { + "amount": "0.14545455", + "date": "2020-09-14 03:04:55", + "globalTradeID": 487253238, + "orderNumber": 494125914579, + "rate": "0.00824999", + "total": "0.00119999", + "tradeID": 20587545, + "type": "buy" + }, + { + "amount": "0.00048150", + "date": "2020-09-14 03:03:51", + "globalTradeID": 487253142, + "orderNumber": 494125804689, + "rate": "0.00824500", + "total": "0.00000396", + "tradeID": 20587544, + "type": "sell" + }, + { + "amount": "0.00039724", + "date": "2020-09-14 03:03:50", + "globalTradeID": 487253141, + "orderNumber": 494125803690, + "rate": "0.00825999", + "total": "0.00000328", + "tradeID": 20587543, + "type": "buy" + }, + { + "amount": "0.00026925", + "date": "2020-09-14 03:03:45", + "globalTradeID": 487253124, + "orderNumber": 494125802691, + "rate": "0.00824500", + "total": "0.00000221", + "tradeID": 20587542, + "type": "sell" + }, + { + "amount": "0.00021224", + "date": "2020-09-14 03:03:44", + "globalTradeID": 487253122, + "orderNumber": 494125801692, + "rate": "0.00824500", + "total": "0.00000174", + "tradeID": 20587541, + "type": "sell" + }, + { + "amount": "3.57000000", + "date": "2020-09-14 03:02:08", + "globalTradeID": 487252943, + "orderNumber": 494125573920, + "rate": "0.00825088", + "total": "0.02945564", + "tradeID": 20587540, + "type": "buy" + }, + { + "amount": "7.27599999", + "date": "2020-09-14 03:02:08", + "globalTradeID": 487252942, + "orderNumber": 494125573920, + "rate": "0.00825087", + "total": "0.06003333", + "tradeID": 20587539, + "type": "buy" + }, + { + "amount": "3.53500000", + "date": "2020-09-14 03:02:07", + "globalTradeID": 487252938, + "orderNumber": 494125554939, + "rate": "0.00825088", + "total": "0.02916686", + "tradeID": 20587538, + "type": "buy" + }, + { + "amount": "4.99276662", + "date": "2020-09-14 03:02:04", + "globalTradeID": 487252934, + "orderNumber": 494125519974, + "rate": "0.00821045", + "total": "0.04099286", + "tradeID": 20587537, + "type": "sell" + }, + { + "amount": "0.01789760", + "date": "2020-09-14 03:02:04", + "globalTradeID": 487252933, + "orderNumber": 494125519974, + "rate": "0.00822870", + "total": "0.00014727", + "tradeID": 20587536, + "type": "sell" + }, + { + "amount": "3.53500000", + "date": "2020-09-14 03:02:04", + "globalTradeID": 487252932, + "orderNumber": 494125519974, + "rate": "0.00824109", + "total": "0.02913225", + "tradeID": 20587535, + "type": "sell" + }, + { + "amount": "8.99345000", + "date": "2020-09-14 03:02:04", + "globalTradeID": 487252931, + "orderNumber": 494125519974, + "rate": "0.00824503", + "total": "0.07415126", + "tradeID": 20587534, + "type": "sell" + }, + { + "amount": "5.82690000", + "date": "2020-09-14 03:02:04", + "globalTradeID": 487252930, + "orderNumber": 494125519974, + "rate": "0.00825000", + "total": "0.04807192", + "tradeID": 20587533, + "type": "sell" + }, + { + "amount": "0.53203997", + "date": "2020-09-14 03:01:27", + "globalTradeID": 487252846, + "orderNumber": 494125405089, + "rate": "0.00824000", + "total": "0.00438400", + "tradeID": 20587532, + "type": "sell" + }, + { + "amount": "0.00030321", + "date": "2020-09-14 02:59:46", + "globalTradeID": 487252622, + "orderNumber": 494125087407, + "rate": "0.00824501", + "total": "0.00000249", + "tradeID": 20587531, + "type": "sell" + }, + { + "amount": "0.00004387", + "date": "2020-09-14 02:59:45", + "globalTradeID": 487252621, + "orderNumber": 494125086408, + "rate": "0.00825475", + "total": "0.00000036", + "tradeID": 20587530, + "type": "buy" + }, + { + "amount": "0.94245482", + "date": "2020-09-14 02:57:53", + "globalTradeID": 487252375, + "orderNumber": 494124790704, + "rate": "0.00824918", + "total": "0.00777447", + "tradeID": 20587529, + "type": "sell" + }, + { + "amount": "0.00010425", + "date": "2020-09-14 02:56:58", + "globalTradeID": 487252288, + "orderNumber": 494124696798, + "rate": "0.00824921", + "total": "0.00000085", + "tradeID": 20587528, + "type": "sell" + }, + { + "amount": "0.00006474", + "date": "2020-09-14 02:56:58", + "globalTradeID": 487252287, + "orderNumber": 494124694800, + "rate": "0.00826012", + "total": "0.00000053", + "tradeID": 20587527, + "type": "buy" + }, + { + "amount": "0.00149196", + "date": "2020-09-14 02:54:14", + "globalTradeID": 487251974, + "orderNumber": 494124369126, + "rate": "0.00826155", + "total": "0.00001232", + "tradeID": 20587526, + "type": "buy" + }, + { + "amount": "0.00011273", + "date": "2020-09-14 02:54:09", + "globalTradeID": 487251950, + "orderNumber": 494124357138, + "rate": "0.00824919", + "total": "0.00000092", + "tradeID": 20587525, + "type": "sell" + }, + { + "amount": "0.00019053", + "date": "2020-09-14 02:52:34", + "globalTradeID": 487251743, + "orderNumber": 494124141354, + "rate": "0.00825500", + "total": "0.00000157", + "tradeID": 20587524, + "type": "buy" + }, + { + "amount": "4.71227401", + "date": "2020-09-14 02:51:47", + "globalTradeID": 487251647, + "orderNumber": 494124008487, + "rate": "0.00825418", + "total": "0.03889595", + "tradeID": 20587523, + "type": "sell" + }, + { + "amount": "23.56137013", + "date": "2020-09-14 02:51:30", + "globalTradeID": 487251615, + "orderNumber": 494123954541, + "rate": "0.00826420", + "total": "0.19471587", + "tradeID": 20587522, + "type": "sell" + }, + { + "amount": "0.00003053", + "date": "2020-09-14 02:50:56", + "globalTradeID": 487251553, + "orderNumber": 494123893602, + "rate": "0.00827141", + "total": "0.00000025", + "tradeID": 20587521, + "type": "buy" + }, + { + "amount": "0.00072637", + "date": "2020-09-14 02:50:56", + "globalTradeID": 487251551, + "orderNumber": 494123891604, + "rate": "0.00827141", + "total": "0.00000600", + "tradeID": 20587520, + "type": "buy" + }, + { + "amount": "6.06056875", + "date": "2020-09-14 02:49:50", + "globalTradeID": 487251451, + "orderNumber": 494123722773, + "rate": "0.00826618", + "total": "0.05009775", + "tradeID": 20587519, + "type": "sell" + }, + { + "amount": "0.00010339", + "date": "2020-09-14 02:48:09", + "globalTradeID": 487251292, + "orderNumber": 494123534961, + "rate": "0.00827497", + "total": "0.00000085", + "tradeID": 20587518, + "type": "buy" + }, + { + "amount": "24.18592445", + "date": "2020-09-14 02:47:55", + "globalTradeID": 487251262, + "orderNumber": 494123474022, + "rate": "0.00827417", + "total": "0.20011845", + "tradeID": 20587517, + "type": "sell" + }, + { + "amount": "0.00011550", + "date": "2020-09-14 02:47:02", + "globalTradeID": 487251116, + "orderNumber": 494123367129, + "rate": "0.00828397", + "total": "0.00000095", + "tradeID": 20587516, + "type": "buy" + }, + { + "amount": "0.00005199", + "date": "2020-09-14 02:45:22", + "globalTradeID": 487250914, + "orderNumber": 494123159337, + "rate": "0.00828474", + "total": "0.00000043", + "tradeID": 20587515, + "type": "buy" + }, + { + "amount": "2.91601719", + "date": "2020-09-14 02:44:39", + "globalTradeID": 487250841, + "orderNumber": 494123073423, + "rate": "0.00827418", + "total": "0.02412765", + "tradeID": 20587514, + "type": "sell" + }, + { + "amount": "0.00005916", + "date": "2020-09-14 02:43:48", + "globalTradeID": 487250752, + "orderNumber": 494122958538, + "rate": "0.00828627", + "total": "0.00000049", + "tradeID": 20587513, + "type": "buy" + }, + { + "amount": "0.00000240", + "date": "2020-09-14 02:42:31", + "globalTradeID": 487250598, + "orderNumber": 494122805691, + "rate": "0.00828650", + "total": "0.00000001", + "tradeID": 20587512, + "type": "buy" + }, + { + "amount": "0.00038167", + "date": "2020-09-14 02:42:30", + "globalTradeID": 487250596, + "orderNumber": 494122804692, + "rate": "0.00828650", + "total": "0.00000316", + "tradeID": 20587511, + "type": "buy" + }, + { + "amount": "0.00045197", + "date": "2020-09-14 02:42:28", + "globalTradeID": 487250582, + "orderNumber": 494122798698, + "rate": "0.00827472", + "total": "0.00000373", + "tradeID": 20587510, + "type": "sell" + }, + { + "amount": "0.00009063", + "date": "2020-09-14 02:42:27", + "globalTradeID": 487250580, + "orderNumber": 494122797699, + "rate": "0.00827472", + "total": "0.00000074", + "tradeID": 20587509, + "type": "sell" + }, + { + "amount": "0.00000240", + "date": "2020-09-14 02:35:52", + "globalTradeID": 487249796, + "orderNumber": 494122171326, + "rate": "0.00827627", + "total": "0.00000001", + "tradeID": 20587508, + "type": "buy" + }, + { + "amount": "0.00000240", + "date": "2020-09-14 02:35:51", + "globalTradeID": 487249793, + "orderNumber": 494122169328, + "rate": "0.00827627", + "total": "0.00000001", + "tradeID": 20587507, + "type": "buy" + }, + { + "amount": "0.00116014", + "date": "2020-09-14 02:35:50", + "globalTradeID": 487249786, + "orderNumber": 494122165332, + "rate": "0.00827627", + "total": "0.00000960", + "tradeID": 20587506, + "type": "buy" + }, + { + "amount": "0.12993270", + "date": "2020-09-14 02:34:01", + "globalTradeID": 487249523, + "orderNumber": 494121954543, + "rate": "0.00826517", + "total": "0.00107391", + "tradeID": 20587505, + "type": "buy" + }, + { + "amount": "1.15586434", + "date": "2020-09-14 02:33:32", + "globalTradeID": 487249482, + "orderNumber": 494121936561, + "rate": "0.00826418", + "total": "0.00955227", + "tradeID": 20587504, + "type": "sell" + }, + { + "amount": "0.00006730", + "date": "2020-09-14 02:33:06", + "globalTradeID": 487249437, + "orderNumber": 494121907590, + "rate": "0.00826517", + "total": "0.00000055", + "tradeID": 20587503, + "type": "buy" + }, + { + "amount": "0.00010164", + "date": "2020-09-14 02:33:04", + "globalTradeID": 487249432, + "orderNumber": 494121902595, + "rate": "0.00826418", + "total": "0.00000083", + "tradeID": 20587502, + "type": "sell" + }, + { + "amount": "2.92343232", + "date": "2020-09-14 02:31:30", + "globalTradeID": 487249300, + "orderNumber": 494121729768, + "rate": "0.00826517", + "total": "0.02416266", + "tradeID": 20587501, + "type": "sell" + }, + { + "amount": "0.00005081", + "date": "2020-09-14 02:31:27", + "globalTradeID": 487249292, + "orderNumber": 494121722775, + "rate": "0.00826514", + "total": "0.00000041", + "tradeID": 20587500, + "type": "sell" + }, + { + "amount": "0.00038525", + "date": "2020-09-14 02:30:21", + "globalTradeID": 487249178, + "orderNumber": 494121588909, + "rate": "0.00826999", + "total": "0.00000318", + "tradeID": 20587499, + "type": "buy" + }, + { + "amount": "2.06363920", + "date": "2020-09-14 02:29:28", + "globalTradeID": 487249078, + "orderNumber": 494121471027, + "rate": "0.00825918", + "total": "0.01704396", + "tradeID": 20587498, + "type": "sell" + }, + { + "amount": "0.49050900", + "date": "2020-09-14 02:28:57", + "globalTradeID": 487249014, + "orderNumber": 494121410088, + "rate": "0.00826332", + "total": "0.00405323", + "tradeID": 20587497, + "type": "buy" + }, + { + "amount": "0.00001627", + "date": "2020-09-14 02:27:38", + "globalTradeID": 487248878, + "orderNumber": 494121259239, + "rate": "0.00826807", + "total": "0.00000013", + "tradeID": 20587496, + "type": "buy" + }, + { + "amount": "0.00011157", + "date": "2020-09-14 02:27:37", + "globalTradeID": 487248871, + "orderNumber": 494121258240, + "rate": "0.00826807", + "total": "0.00000092", + "tradeID": 20587495, + "type": "buy" + }, + { + "amount": "0.00012478", + "date": "2020-09-14 02:27:33", + "globalTradeID": 487248855, + "orderNumber": 494121252246, + "rate": "0.00825501", + "total": "0.00000103", + "tradeID": 20587494, + "type": "sell" + }, + { + "amount": "0.00005087", + "date": "2020-09-14 02:27:30", + "globalTradeID": 487248846, + "orderNumber": 494121249249, + "rate": "0.00825501", + "total": "0.00000041", + "tradeID": 20587493, + "type": "sell" + }, + { + "amount": "2.92775751", + "date": "2020-09-14 02:27:26", + "globalTradeID": 487248830, + "orderNumber": 494121243255, + "rate": "0.00825501", + "total": "0.02416866", + "tradeID": 20587492, + "type": "sell" + }, + { + "amount": "0.92958195", + "date": "2020-09-14 02:26:58", + "globalTradeID": 487248787, + "orderNumber": 494121208290, + "rate": "0.00826500", + "total": "0.00768299", + "tradeID": 20587491, + "type": "buy" + }, + { + "amount": "22.45748062", + "date": "2020-09-14 02:26:58", + "globalTradeID": 487248786, + "orderNumber": 494121208290, + "rate": "0.00826499", + "total": "0.18561085", + "tradeID": 20587490, + "type": "buy" + }, + { + "amount": "0.00029542", + "date": "2020-09-14 02:25:48", + "globalTradeID": 487248662, + "orderNumber": 494121079419, + "rate": "0.00825917", + "total": "0.00000243", + "tradeID": 20587489, + "type": "sell" + }, + { + "amount": "0.14450314", + "date": "2020-09-14 02:25:22", + "globalTradeID": 487248606, + "orderNumber": 494121037461, + "rate": "0.00825918", + "total": "0.00119347", + "tradeID": 20587488, + "type": "sell" + }, + { + "amount": "0.14511366", + "date": "2020-09-14 02:24:55", + "globalTradeID": 487248560, + "orderNumber": 494120973525, + "rate": "0.00826935", + "total": "0.00119999", + "tradeID": 20587487, + "type": "buy" + }, + { + "amount": "1.21555509", + "date": "2020-09-14 02:24:07", + "globalTradeID": 487248413, + "orderNumber": 494120850648, + "rate": "0.00825001", + "total": "0.01002834", + "tradeID": 20587486, + "type": "sell" + }, + { + "amount": "3.53500000", + "date": "2020-09-14 02:24:00", + "globalTradeID": 487248389, + "orderNumber": 494120775723, + "rate": "0.00825569", + "total": "0.02918386", + "tradeID": 20587485, + "type": "buy" + }, + { + "amount": "6.40849687", + "date": "2020-09-14 02:24:00", + "globalTradeID": 487248388, + "orderNumber": 494120775723, + "rate": "0.00825567", + "total": "0.05290643", + "tradeID": 20587484, + "type": "buy" + }, + { + "amount": "0.31148689", + "date": "2020-09-14 02:23:57", + "globalTradeID": 487248383, + "orderNumber": 494120740758, + "rate": "0.00822396", + "total": "0.00256165", + "tradeID": 20587483, + "type": "sell" + }, + { + "amount": "0.88400000", + "date": "2020-09-14 02:23:57", + "globalTradeID": 487248382, + "orderNumber": 494120740758, + "rate": "0.00825067", + "total": "0.00729359", + "tradeID": 20587482, + "type": "sell" + }, + { + "amount": "1.24594430", + "date": "2020-09-14 02:23:56", + "globalTradeID": 487248379, + "orderNumber": 494120724774, + "rate": "0.00822767", + "total": "0.01025121", + "tradeID": 20587481, + "type": "buy" + }, + { + "amount": "2.71636442", + "date": "2020-09-14 02:23:56", + "globalTradeID": 487248378, + "orderNumber": 494120719779, + "rate": "0.00822000", + "total": "0.02232851", + "tradeID": 20587480, + "type": "buy" + }, + { + "amount": "2.84400000", + "date": "2020-09-14 02:23:56", + "globalTradeID": 487248375, + "orderNumber": 494120717781, + "rate": "0.00822000", + "total": "0.02337768", + "tradeID": 20587479, + "type": "buy" + }, + { + "amount": "15.40000000", + "date": "2020-09-14 02:23:55", + "globalTradeID": 487248373, + "orderNumber": 494120713785, + "rate": "0.00822000", + "total": "0.12658800", + "tradeID": 20587478, + "type": "buy" + }, + { + "amount": "0.88469999", + "date": "2020-09-14 02:23:55", + "globalTradeID": 487248372, + "orderNumber": 494120711787, + "rate": "0.00822000", + "total": "0.00727223", + "tradeID": 20587477, + "type": "buy" + }, + { + "amount": "10.63258957", + "date": "2020-09-14 02:23:55", + "globalTradeID": 487248369, + "orderNumber": 494120709789, + "rate": "0.00822000", + "total": "0.08739988", + "tradeID": 20587476, + "type": "buy" + }, + { + "amount": "1.17518248", + "date": "2020-09-14 02:23:55", + "globalTradeID": 487248368, + "orderNumber": 494120706792, + "rate": "0.00822000", + "total": "0.00965999", + "tradeID": 20587475, + "type": "buy" + }, + { + "amount": "1.17915338", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248364, + "orderNumber": 494120703795, + "rate": "0.00822000", + "total": "0.00969264", + "tradeID": 20587474, + "type": "buy" + }, + { + "amount": "2.84400000", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248361, + "orderNumber": 494120700798, + "rate": "0.00822000", + "total": "0.02337768", + "tradeID": 20587473, + "type": "buy" + }, + { + "amount": "0.88399999", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248360, + "orderNumber": 494120698800, + "rate": "0.00822000", + "total": "0.00726647", + "tradeID": 20587472, + "type": "buy" + }, + { + "amount": "0.88479999", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248359, + "orderNumber": 494120697801, + "rate": "0.00822000", + "total": "0.00727305", + "tradeID": 20587471, + "type": "buy" + }, + { + "amount": "74.20000000", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248358, + "orderNumber": 494120695803, + "rate": "0.00822000", + "total": "0.60992400", + "tradeID": 20587470, + "type": "buy" + }, + { + "amount": "24.24689664", + "date": "2020-09-14 02:23:54", + "globalTradeID": 487248357, + "orderNumber": 494120692806, + "rate": "0.00822000", + "total": "0.19930949", + "tradeID": 20587469, + "type": "buy" + }, + { + "amount": "1.19870000", + "date": "2020-09-14 02:23:52", + "globalTradeID": 487248350, + "orderNumber": 494120684814, + "rate": "0.00822000", + "total": "0.00985331", + "tradeID": 20587468, + "type": "buy" + }, + { + "amount": "1.17530413", + "date": "2020-09-14 02:23:51", + "globalTradeID": 487248348, + "orderNumber": 494120681817, + "rate": "0.00822000", + "total": "0.00966099", + "tradeID": 20587467, + "type": "buy" + }, + { + "amount": "1.17911641", + "date": "2020-09-14 02:23:51", + "globalTradeID": 487248344, + "orderNumber": 494120680818, + "rate": "0.00822000", + "total": "0.00969233", + "tradeID": 20587466, + "type": "buy" + }, + { + "amount": "9.80000000", + "date": "2020-09-14 02:23:51", + "globalTradeID": 487248342, + "orderNumber": 494120678820, + "rate": "0.00822000", + "total": "0.08055600", + "tradeID": 20587465, + "type": "buy" + }, + { + "amount": "7.17066402", + "date": "2020-09-14 02:23:49", + "globalTradeID": 487248339, + "orderNumber": 494120673825, + "rate": "0.00822000", + "total": "0.05894285", + "tradeID": 20587464, + "type": "buy" + }, + { + "amount": "2.84400000", + "date": "2020-09-14 02:23:49", + "globalTradeID": 487248337, + "orderNumber": 494120672826, + "rate": "0.00822000", + "total": "0.02337768", + "tradeID": 20587463, + "type": "buy" + }, + { + "amount": "0.23865362", + "date": "2020-09-14 02:23:48", + "globalTradeID": 487248335, + "orderNumber": 494120671827, + "rate": "0.00822000", + "total": "0.00196173", + "tradeID": 20587462, + "type": "buy" + }, + { + "amount": "2.54706830", + "date": "2020-09-14 02:23:48", + "globalTradeID": 487248333, + "orderNumber": 494120669829, + "rate": "0.00822000", + "total": "0.02093690", + "tradeID": 20587461, + "type": "buy" + }, + { + "amount": "0.23865362", + "date": "2020-09-14 02:23:48", + "globalTradeID": 487248331, + "orderNumber": 494120667831, + "rate": "0.00822000", + "total": "0.00196173", + "tradeID": 20587460, + "type": "buy" + }, + { + "amount": "1.19452554", + "date": "2020-09-14 02:23:48", + "globalTradeID": 487248328, + "orderNumber": 494120664834, + "rate": "0.00822000", + "total": "0.00981899", + "tradeID": 20587459, + "type": "buy" + } + ], + "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "3.21720471", + "date": "2020-06-06 00:59:21", + "globalTradeID": 469013857, + "orderNumber": 475804187646, + "rate": "0.00702980", + "total": "0.02261630", + "tradeID": 20409261, + "type": "sell" + }, + { + "amount": "0.00095095", + "date": "2020-06-06 00:58:46", + "globalTradeID": 469013804, + "orderNumber": 475804160673, + "rate": "0.00702450", + "total": "0.00000667", + "tradeID": 20409260, + "type": "sell" + }, + { + "amount": "0.04806103", + "date": "2020-06-06 00:56:53", + "globalTradeID": 469013609, + "orderNumber": 475804081752, + "rate": "0.00702981", + "total": "0.00033785", + "tradeID": 20409259, + "type": "buy" + }, + { + "amount": "0.14791082", + "date": "2020-06-06 00:56:14", + "globalTradeID": 469013545, + "orderNumber": 475804064769, + "rate": "0.00702981", + "total": "0.00103978", + "tradeID": 20409258, + "type": "buy" + }, + { + "amount": "0.60514301", + "date": "2020-06-06 00:55:54", + "globalTradeID": 469013498, + "orderNumber": 475804051782, + "rate": "0.00702981", + "total": "0.00425404", + "tradeID": 20409257, + "type": "buy" + }, + { + "amount": "0.00012547", + "date": "2020-06-06 00:51:57", + "globalTradeID": 469013113, + "orderNumber": 475803828006, + "rate": "0.00701340", + "total": "0.00000087", + "tradeID": 20409256, + "type": "sell" + }, + { + "amount": "2.93691436", + "date": "2020-06-06 00:49:28", + "globalTradeID": 469012836, + "orderNumber": 475803574260, + "rate": "0.00702981", + "total": "0.02064594", + "tradeID": 20409255, + "type": "buy" + }, + { + "amount": "2.58959011", + "date": "2020-06-06 00:49:14", + "globalTradeID": 469012793, + "orderNumber": 475803547287, + "rate": "0.00702981", + "total": "0.01820432", + "tradeID": 20409254, + "type": "buy" + }, + { + "amount": "2.58959011", + "date": "2020-06-06 00:49:14", + "globalTradeID": 469012792, + "orderNumber": 475803544290, + "rate": "0.00702981", + "total": "0.01820432", + "tradeID": 20409253, + "type": "buy" + }, + { + "amount": "0.12564003", + "date": "2020-06-06 00:48:10", + "globalTradeID": 469012574, + "orderNumber": 475803440394, + "rate": "0.00702981", + "total": "0.00088322", + "tradeID": 20409252, + "type": "buy" + }, + { + "amount": "0.00029089", + "date": "2020-06-06 00:43:33", + "globalTradeID": 469011702, + "orderNumber": 475802968866, + "rate": "0.00701289", + "total": "0.00000203", + "tradeID": 20409251, + "type": "sell" + }, + { + "amount": "0.00033785", + "date": "2020-06-06 00:41:49", + "globalTradeID": 469011340, + "orderNumber": 475802691144, + "rate": "0.00701475", + "total": "0.00000236", + "tradeID": 20409250, + "type": "sell" + }, + { + "amount": "0.00011689", + "date": "2020-06-06 00:41:48", + "globalTradeID": 469011337, + "orderNumber": 475802688147, + "rate": "0.00701474", + "total": "0.00000081", + "tradeID": 20409249, + "type": "sell" + }, + { + "amount": "0.01809788", + "date": "2020-06-06 00:40:06", + "globalTradeID": 469011032, + "orderNumber": 475802513322, + "rate": "0.00700966", + "total": "0.00012685", + "tradeID": 20409248, + "type": "sell" + }, + { + "amount": "0.00011984", + "date": "2020-06-06 00:36:50", + "globalTradeID": 469010291, + "orderNumber": 475802093742, + "rate": "0.00700877", + "total": "0.00000083", + "tradeID": 20409247, + "type": "sell" + }, + { + "amount": "0.00057297", + "date": "2020-06-06 00:27:02", + "globalTradeID": 469008684, + "orderNumber": 475801024812, + "rate": "0.00699862", + "total": "0.00000400", + "tradeID": 20409246, + "type": "sell" + }, + { + "amount": "0.00020004", + "date": "2020-06-06 00:27:00", + "globalTradeID": 469008674, + "orderNumber": 475801014822, + "rate": "0.00699853", + "total": "0.00000139", + "tradeID": 20409245, + "type": "sell" + }, + { + "amount": "0.00032580", + "date": "2020-06-06 00:25:23", + "globalTradeID": 469008435, + "orderNumber": 475800824013, + "rate": "0.00699804", + "total": "0.00000227", + "tradeID": 20409244, + "type": "sell" + }, + { + "amount": "0.06155579", + "date": "2020-06-06 00:25:06", + "globalTradeID": 469008391, + "orderNumber": 475800772065, + "rate": "0.00701396", + "total": "0.00043174", + "tradeID": 20409243, + "type": "buy" + }, + { + "amount": "0.08703496", + "date": "2020-06-06 00:24:58", + "globalTradeID": 469008369, + "orderNumber": 475800754083, + "rate": "0.00701396", + "total": "0.00061045", + "tradeID": 20409242, + "type": "buy" + }, + { + "amount": "0.00006857", + "date": "2020-06-06 00:20:23", + "globalTradeID": 469007636, + "orderNumber": 475800234603, + "rate": "0.00699981", + "total": "0.00000047", + "tradeID": 20409241, + "type": "sell" + }, + { + "amount": "0.00022429", + "date": "2020-06-06 00:20:21", + "globalTradeID": 469007626, + "orderNumber": 475800229608, + "rate": "0.00699964", + "total": "0.00000156", + "tradeID": 20409240, + "type": "sell" + }, + { + "amount": "0.00030155", + "date": "2020-06-06 00:18:44", + "globalTradeID": 469007424, + "orderNumber": 475800039798, + "rate": "0.00699713", + "total": "0.00000210", + "tradeID": 20409239, + "type": "sell" + }, + { + "amount": "0.00016573", + "date": "2020-06-06 00:15:31", + "globalTradeID": 469006942, + "orderNumber": 475799680158, + "rate": "0.00699921", + "total": "0.00000115", + "tradeID": 20409238, + "type": "sell" + }, + { + "amount": "0.03876964", + "date": "2020-06-06 00:13:16", + "globalTradeID": 469006371, + "orderNumber": 475799335503, + "rate": "0.00702776", + "total": "0.00027246", + "tradeID": 20409237, + "type": "sell" + }, + { + "amount": "0.02573029", + "date": "2020-06-06 00:12:08", + "globalTradeID": 469006150, + "orderNumber": 475799283555, + "rate": "0.00702776", + "total": "0.00018082", + "tradeID": 20409236, + "type": "sell" + }, + { + "amount": "1.49550007", + "date": "2020-06-06 00:11:38", + "globalTradeID": 469006063, + "orderNumber": 475799249589, + "rate": "0.00702776", + "total": "0.01051001", + "tradeID": 20409235, + "type": "buy" + }, + { + "amount": "0.01835715", + "date": "2020-06-06 00:08:19", + "globalTradeID": 469005543, + "orderNumber": 475798845993, + "rate": "0.00702000", + "total": "0.00012886", + "tradeID": 20409234, + "type": "buy" + }, + { + "amount": "0.00000285", + "date": "2020-06-06 00:05:46", + "globalTradeID": 469005149, + "orderNumber": 475798564275, + "rate": "0.00700393", + "total": "0.00000001", + "tradeID": 20409233, + "type": "sell" + }, + { + "amount": "1.82932923", + "date": "2020-06-06 00:04:27", + "globalTradeID": 469004901, + "orderNumber": 475798401438, + "rate": "0.00700160", + "total": "0.01280823", + "tradeID": 20409232, + "type": "sell" + }, + { + "amount": "1.06056403", + "date": "2020-06-06 00:04:27", + "globalTradeID": 469004900, + "orderNumber": 475798401438, + "rate": "0.00701499", + "total": "0.00743984", + "tradeID": 20409231, + "type": "sell" + }, + { + "amount": "0.19919400", + "date": "2020-06-06 00:03:54", + "globalTradeID": 469004795, + "orderNumber": 475798363476, + "rate": "0.00701499", + "total": "0.00139734", + "tradeID": 20409230, + "type": "buy" + }, + { + "amount": "1.09717879", + "date": "2020-06-06 00:02:07", + "globalTradeID": 469004439, + "orderNumber": 475798123716, + "rate": "0.00701999", + "total": "0.00770218", + "tradeID": 20409229, + "type": "sell" + }, + { + "amount": "0.04295869", + "date": "2020-06-06 00:02:02", + "globalTradeID": 469004417, + "orderNumber": 475798114725, + "rate": "0.00701999", + "total": "0.00030156", + "tradeID": 20409228, + "type": "sell" + }, + { + "amount": "0.98890207", + "date": "2020-06-06 00:01:55", + "globalTradeID": 469004399, + "orderNumber": 475798102737, + "rate": "0.00701999", + "total": "0.00694208", + "tradeID": 20409227, + "type": "sell" + }, + { + "amount": "0.98970300", + "date": "2020-06-06 00:01:54", + "globalTradeID": 469004393, + "orderNumber": 475798101738, + "rate": "0.00701999", + "total": "0.00694770", + "tradeID": 20409226, + "type": "sell" + }, + { + "amount": "0.02860000", + "date": "2020-06-06 00:01:12", + "globalTradeID": 469004227, + "orderNumber": 475798036803, + "rate": "0.00701999", + "total": "0.00020077", + "tradeID": 20409225, + "type": "buy" + }, + { + "amount": "0.00002285", + "date": "2020-06-06 00:00:43", + "globalTradeID": 469004013, + "orderNumber": 475797933906, + "rate": "0.00700206", + "total": "0.00000015", + "tradeID": 20409224, + "type": "sell" + } + ], + "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR\u0026end=1591405200\u0026start=1591401600", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "3.21720471", + "date": "2020-06-06 00:59:21", + "globalTradeID": 469013857, + "orderNumber": 475804187646, + "rate": "0.00702980", + "total": "0.02261630", + "tradeID": 20409261, + "type": "sell" + }, + { + "amount": "0.00095095", + "date": "2020-06-06 00:58:46", + "globalTradeID": 469013804, + "orderNumber": 475804160673, + "rate": "0.00702450", + "total": "0.00000667", + "tradeID": 20409260, + "type": "sell" + }, + { + "amount": "0.04806103", + "date": "2020-06-06 00:56:53", + "globalTradeID": 469013609, + "orderNumber": 475804081752, + "rate": "0.00702981", + "total": "0.00033785", + "tradeID": 20409259, + "type": "buy" + }, + { + "amount": "0.14791082", + "date": "2020-06-06 00:56:14", + "globalTradeID": 469013545, + "orderNumber": 475804064769, + "rate": "0.00702981", + "total": "0.00103978", + "tradeID": 20409258, + "type": "buy" + }, + { + "amount": "0.60514301", + "date": "2020-06-06 00:55:54", + "globalTradeID": 469013498, + "orderNumber": 475804051782, + "rate": "0.00702981", + "total": "0.00425404", + "tradeID": 20409257, + "type": "buy" + }, + { + "amount": "0.00012547", + "date": "2020-06-06 00:51:57", + "globalTradeID": 469013113, + "orderNumber": 475803828006, + "rate": "0.00701340", + "total": "0.00000087", + "tradeID": 20409256, + "type": "sell" + }, + { + "amount": "2.93691436", + "date": "2020-06-06 00:49:28", + "globalTradeID": 469012836, + "orderNumber": 475803574260, + "rate": "0.00702981", + "total": "0.02064594", + "tradeID": 20409255, + "type": "buy" + }, + { + "amount": "2.58959011", + "date": "2020-06-06 00:49:14", + "globalTradeID": 469012793, + "orderNumber": 475803547287, + "rate": "0.00702981", + "total": "0.01820432", + "tradeID": 20409254, + "type": "buy" + }, + { + "amount": "2.58959011", + "date": "2020-06-06 00:49:14", + "globalTradeID": 469012792, + "orderNumber": 475803544290, + "rate": "0.00702981", + "total": "0.01820432", + "tradeID": 20409253, + "type": "buy" + }, + { + "amount": "0.12564003", + "date": "2020-06-06 00:48:10", + "globalTradeID": 469012574, + "orderNumber": 475803440394, + "rate": "0.00702981", + "total": "0.00088322", + "tradeID": 20409252, + "type": "buy" + }, + { + "amount": "0.00029089", + "date": "2020-06-06 00:43:33", + "globalTradeID": 469011702, + "orderNumber": 475802968866, + "rate": "0.00701289", + "total": "0.00000203", + "tradeID": 20409251, + "type": "sell" + }, + { + "amount": "0.00033785", + "date": "2020-06-06 00:41:49", + "globalTradeID": 469011340, + "orderNumber": 475802691144, + "rate": "0.00701475", + "total": "0.00000236", + "tradeID": 20409250, + "type": "sell" + }, + { + "amount": "0.00011689", + "date": "2020-06-06 00:41:48", + "globalTradeID": 469011337, + "orderNumber": 475802688147, + "rate": "0.00701474", + "total": "0.00000081", + "tradeID": 20409249, + "type": "sell" + }, + { + "amount": "0.01809788", + "date": "2020-06-06 00:40:06", + "globalTradeID": 469011032, + "orderNumber": 475802513322, + "rate": "0.00700966", + "total": "0.00012685", + "tradeID": 20409248, + "type": "sell" + }, + { + "amount": "0.00011984", + "date": "2020-06-06 00:36:50", + "globalTradeID": 469010291, + "orderNumber": 475802093742, + "rate": "0.00700877", + "total": "0.00000083", + "tradeID": 20409247, + "type": "sell" + }, + { + "amount": "0.00057297", + "date": "2020-06-06 00:27:02", + "globalTradeID": 469008684, + "orderNumber": 475801024812, + "rate": "0.00699862", + "total": "0.00000400", + "tradeID": 20409246, + "type": "sell" + }, + { + "amount": "0.00020004", + "date": "2020-06-06 00:27:00", + "globalTradeID": 469008674, + "orderNumber": 475801014822, + "rate": "0.00699853", + "total": "0.00000139", + "tradeID": 20409245, + "type": "sell" + }, + { + "amount": "0.00032580", + "date": "2020-06-06 00:25:23", + "globalTradeID": 469008435, + "orderNumber": 475800824013, + "rate": "0.00699804", + "total": "0.00000227", + "tradeID": 20409244, + "type": "sell" + }, + { + "amount": "0.06155579", + "date": "2020-06-06 00:25:06", + "globalTradeID": 469008391, + "orderNumber": 475800772065, + "rate": "0.00701396", + "total": "0.00043174", + "tradeID": 20409243, + "type": "buy" + }, + { + "amount": "0.08703496", + "date": "2020-06-06 00:24:58", + "globalTradeID": 469008369, + "orderNumber": 475800754083, + "rate": "0.00701396", + "total": "0.00061045", + "tradeID": 20409242, + "type": "buy" + }, + { + "amount": "0.00006857", + "date": "2020-06-06 00:20:23", + "globalTradeID": 469007636, + "orderNumber": 475800234603, + "rate": "0.00699981", + "total": "0.00000047", + "tradeID": 20409241, + "type": "sell" + }, + { + "amount": "0.00022429", + "date": "2020-06-06 00:20:21", + "globalTradeID": 469007626, + "orderNumber": 475800229608, + "rate": "0.00699964", + "total": "0.00000156", + "tradeID": 20409240, + "type": "sell" + }, + { + "amount": "0.00030155", + "date": "2020-06-06 00:18:44", + "globalTradeID": 469007424, + "orderNumber": 475800039798, + "rate": "0.00699713", + "total": "0.00000210", + "tradeID": 20409239, + "type": "sell" + }, + { + "amount": "0.00016573", + "date": "2020-06-06 00:15:31", + "globalTradeID": 469006942, + "orderNumber": 475799680158, + "rate": "0.00699921", + "total": "0.00000115", + "tradeID": 20409238, + "type": "sell" + }, + { + "amount": "0.03876964", + "date": "2020-06-06 00:13:16", + "globalTradeID": 469006371, + "orderNumber": 475799335503, + "rate": "0.00702776", + "total": "0.00027246", + "tradeID": 20409237, + "type": "sell" + }, + { + "amount": "0.02573029", + "date": "2020-06-06 00:12:08", + "globalTradeID": 469006150, + "orderNumber": 475799283555, + "rate": "0.00702776", + "total": "0.00018082", + "tradeID": 20409236, + "type": "sell" + }, + { + "amount": "1.49550007", + "date": "2020-06-06 00:11:38", + "globalTradeID": 469006063, + "orderNumber": 475799249589, + "rate": "0.00702776", + "total": "0.01051001", + "tradeID": 20409235, + "type": "buy" + }, + { + "amount": "0.01835715", + "date": "2020-06-06 00:08:19", + "globalTradeID": 469005543, + "orderNumber": 475798845993, + "rate": "0.00702000", + "total": "0.00012886", + "tradeID": 20409234, + "type": "buy" + }, + { + "amount": "0.00000285", + "date": "2020-06-06 00:05:46", + "globalTradeID": 469005149, + "orderNumber": 475798564275, + "rate": "0.00700393", + "total": "0.00000001", + "tradeID": 20409233, + "type": "sell" + }, + { + "amount": "1.82932923", + "date": "2020-06-06 00:04:27", + "globalTradeID": 469004901, + "orderNumber": 475798401438, + "rate": "0.00700160", + "total": "0.01280823", + "tradeID": 20409232, + "type": "sell" + }, + { + "amount": "1.06056403", + "date": "2020-06-06 00:04:27", + "globalTradeID": 469004900, + "orderNumber": 475798401438, + "rate": "0.00701499", + "total": "0.00743984", + "tradeID": 20409231, + "type": "sell" + }, + { + "amount": "0.19919400", + "date": "2020-06-06 00:03:54", + "globalTradeID": 469004795, + "orderNumber": 475798363476, + "rate": "0.00701499", + "total": "0.00139734", + "tradeID": 20409230, + "type": "buy" + }, + { + "amount": "1.09717879", + "date": "2020-06-06 00:02:07", + "globalTradeID": 469004439, + "orderNumber": 475798123716, + "rate": "0.00701999", + "total": "0.00770218", + "tradeID": 20409229, + "type": "sell" + }, + { + "amount": "0.04295869", + "date": "2020-06-06 00:02:02", + "globalTradeID": 469004417, + "orderNumber": 475798114725, + "rate": "0.00701999", + "total": "0.00030156", + "tradeID": 20409228, + "type": "sell" + }, + { + "amount": "0.98890207", + "date": "2020-06-06 00:01:55", + "globalTradeID": 469004399, + "orderNumber": 475798102737, + "rate": "0.00701999", + "total": "0.00694208", + "tradeID": 20409227, + "type": "sell" + }, + { + "amount": "0.98970300", + "date": "2020-06-06 00:01:54", + "globalTradeID": 469004393, + "orderNumber": 475798101738, + "rate": "0.00701999", + "total": "0.00694770", + "tradeID": 20409226, + "type": "sell" + }, + { + "amount": "0.02860000", + "date": "2020-06-06 00:01:12", + "globalTradeID": 469004227, + "orderNumber": 475798036803, + "rate": "0.00701999", + "total": "0.00020077", + "tradeID": 20409225, + "type": "buy" + }, + { + "amount": "0.00002285", + "date": "2020-06-06 00:00:43", + "globalTradeID": 469004013, + "orderNumber": 475797933906, + "rate": "0.00700206", + "total": "0.00000015", + "tradeID": 20409224, + "type": "sell" + } + ], + "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR\u0026end=1591405200\u0026start=1591401643", + "bodyParams": "", + "headers": {} } ] }, diff --git a/testdata/http_mock/zb/zb.json b/testdata/http_mock/zb/zb.json index 9f57777c..ad73d651 100644 --- a/testdata/http_mock/zb/zb.json +++ b/testdata/http_mock/zb/zb.json @@ -3206,6 +3206,417 @@ "headers": {} } ] + }, + "/data/v1/trades": { + "GET": [ + { + "data": [ + { + "amount": "0.0003", + "date": 1602036046, + "price": "10584.44", + "tid": 1244927815, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.2423", + "date": 1602036047, + "price": "10579.58", + "tid": 1244927846, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.9465", + "date": 1602036048, + "price": "10583.02", + "tid": 1244927866, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "1.8656", + "date": 1602036049, + "price": "10585.42", + "tid": 1244927886, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "1.8584", + "date": 1602036050, + "price": "10580.21", + "tid": 1244927898, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "1.7062", + "date": 1602036051, + "price": "10579.72", + "tid": 1244927918, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.4845", + "date": 1602036052, + "price": "10581.22", + "tid": 1244927935, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0059", + "date": 1602036053, + "price": "10582.3", + "tid": 1244927955, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0008", + "date": 1602036054, + "price": "10582.8", + "tid": 1244927977, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0001", + "date": 1602036056, + "price": "10583.11", + "tid": 1244928012, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "1.0592", + "date": 1602036057, + "price": "10584.91", + "tid": 1244928040, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.4548", + "date": 1602036058, + "price": "10584.5", + "tid": 1244928062, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0002", + "date": 1602036058, + "price": "10584.5", + "tid": 1244928063, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0025", + "date": 1602036061, + "price": "10583.39", + "tid": 1244928127, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0031", + "date": 1602036063, + "price": "10581.32", + "tid": 1244928176, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0003", + "date": 1602036063, + "price": "10581.32", + "tid": 1244928177, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0006", + "date": 1602036064, + "price": "10584.79", + "tid": 1244928196, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0014", + "date": 1602036064, + "price": "10581.16", + "tid": 1244928197, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.2517", + "date": 1602036066, + "price": "10583.52", + "tid": 1244928235, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0052", + "date": 1602036066, + "price": "10583.52", + "tid": 1244928236, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0003", + "date": 1602036066, + "price": "10583.52", + "tid": 1244928237, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.2190", + "date": 1602036068, + "price": "10582.11", + "tid": 1244928278, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0023", + "date": 1602036068, + "price": "10584.01", + "tid": 1244928279, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0008", + "date": 1602036069, + "price": "10584.74", + "tid": 1244928314, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0001", + "date": 1602036071, + "price": "10580.5", + "tid": 1244928365, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0042", + "date": 1602036072, + "price": "10582.35", + "tid": 1244928376, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0090", + "date": 1602036073, + "price": "10582.71", + "tid": 1244928409, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0017", + "date": 1602036078, + "price": "10581.94", + "tid": 1244928511, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0006", + "date": 1602036078, + "price": "10581.94", + "tid": 1244928512, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0013", + "date": 1602036078, + "price": "10581.94", + "tid": 1244928513, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0002", + "date": 1602036078, + "price": "10581.94", + "tid": 1244928514, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0014", + "date": 1602036080, + "price": "10582.32", + "tid": 1244928557, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0003", + "date": 1602036080, + "price": "10582.32", + "tid": 1244928558, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0014", + "date": 1602036082, + "price": "10584.06", + "tid": 1244928593, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0002", + "date": 1602036082, + "price": "10584.06", + "tid": 1244928594, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0068", + "date": 1602036083, + "price": "10585.31", + "tid": 1244928613, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0593", + "date": 1602036085, + "price": "10585.0", + "tid": 1244928647, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0032", + "date": 1602036085, + "price": "10584.6", + "tid": 1244928648, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0002", + "date": 1602036085, + "price": "10584.6", + "tid": 1244928649, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0434", + "date": 1602036087, + "price": "10583.39", + "tid": 1244928726, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0097", + "date": 1602036087, + "price": "10583.39", + "tid": 1244928727, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0006", + "date": 1602036092, + "price": "10582.6", + "tid": 1244928841, + "trade_type": "ask", + "type": "sell" + }, + { + "amount": "0.0026", + "date": 1602036093, + "price": "10584.47", + "tid": 1244928870, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0008", + "date": 1602036094, + "price": "10585.68", + "tid": 1244928899, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0026", + "date": 1602036094, + "price": "10585.68", + "tid": 1244928900, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0025", + "date": 1602036095, + "price": "10584.05", + "tid": 1244928912, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0022", + "date": 1602036096, + "price": "10582.94", + "tid": 1244928940, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0170", + "date": 1602036097, + "price": "10582.52", + "tid": 1244928956, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "1.1725", + "date": 1602036098, + "price": "10582.83", + "tid": 1244928977, + "trade_type": "bid", + "type": "buy" + }, + { + "amount": "0.0018", + "date": 1602036101, + "price": "10584.75", + "tid": 1244929028, + "trade_type": "bid", + "type": "buy" + } + ], + "queryString": "market=btc_usdt", + "bodyParams": "", + "headers": {} + } + ] } } } \ No newline at end of file