├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.txt ├── README.md ├── appveyor.yml ├── build └── ccxt.browser.js ├── ccxt.browser.js ├── ccxt.d.ts ├── ccxt.js ├── ccxt.php ├── composer.json ├── composer.lock ├── convert-md-2-rst ├── countries.js ├── doc ├── .gitignore ├── FAQ.rst ├── Makefile ├── README.rst ├── _static │ └── css │ │ └── index.css ├── _templates │ └── layout.html ├── conf.py ├── exchanges-by-country.rst ├── exchanges.rst ├── index.rst ├── install.rst ├── make.bat └── manual.rst ├── examples ├── README.md ├── html │ ├── basic-cors-proxy.html │ ├── basic-inheritance.html │ ├── basic-rate-limiting.html │ └── basic.html ├── js │ ├── README.md │ ├── arbitrage-pairs.js │ ├── balances.js │ ├── basic-chart.js │ ├── bcc-vs-bch.js │ ├── binance-fetch-ohlcv.js │ ├── binance-server-time.js │ ├── bitfinex-fetch-trades.js │ ├── bitfinex2-fetch-trades.js │ ├── bittrex-balance.js │ ├── bittrex-fetch-closed-orders-history.js │ ├── builtin-rate-limiting-rest-poller.js │ ├── bypass-cloudflare.js │ ├── cli.js │ ├── cors-proxy.js │ ├── create-order-handle-errors.js │ ├── credentials.json │ ├── cryptopia-fetch-order-books.js │ ├── custom-proxy-url.js │ ├── exchange-capabilities.js │ ├── exchanges.js │ ├── fetch-create-deposit-address.js │ ├── fetch-from-many-exchanges-simultaneously.js │ ├── fetch-ohlcv-cex.js │ ├── fetch-okex-futures.js │ ├── fetch-orders.js │ ├── fetch-ticker-from-multiple-exchanges.js │ ├── fetch-ticker-where-available.js │ ├── hitbtc2-withdraw.js │ ├── instantiate-all-at-once.js │ ├── instantiate-all-from-json.js │ ├── live-orderbook.js │ ├── live-ticker.js │ ├── live-tickers.js │ ├── load-all-symbols-at-once.js │ ├── load-all-tickers-at-once.js │ ├── market-status-and-currency-status.js │ ├── okex-fetch-ohlcv-since-limit.js │ ├── order-book-extra-level-depth-param.js │ ├── poloniex-limits-amount-min.js │ ├── proxy-round-robin.js │ ├── search-all-exchanges.js │ ├── symbols.js │ └── tickers.js ├── php │ ├── README.md │ ├── arbitrage-pairs.php │ ├── basic-error-handling.php │ ├── binance-cancel-order.php │ ├── binance-fetch-ticker.php │ ├── binance-fetch-tickers.php │ ├── bitfinex2-fetch-ohlcv-since-limit.php │ ├── bitfinex2-fetch-ohlcv.php │ ├── bitfinex2-fetch-trades-since.php │ ├── bitmex-create-order.php │ ├── built-in-rate-limiting-poller.php │ ├── cli.php │ ├── error-handling-message.php │ ├── huobi-fetch-balance.php │ ├── indodax-fetch-balance-create-order-cancel-order.php │ ├── kraken-query-ledgers.php │ ├── load-all-at-once.php │ ├── order-book-level-depth-extra-param.php │ ├── react-eventloop-with-rate-limiting.php │ ├── symbols.php │ ├── trading-view.php │ └── vaultoro-fetch-balance.php └── py │ ├── README.md │ ├── arbitrage-pairs.py │ ├── asciichart.py │ ├── async-balance-gdax.py │ ├── async-balance.py │ ├── async-balances.py │ ├── async-basic-rate-limiter.py │ ├── async-basic.py │ ├── async-bitfinex-private-post-account-infos.py │ ├── async-bitstamp-create-limit-buy-order.py │ ├── async-bittrex-orderbook.py │ ├── async-fetch-ticker.py │ ├── async-gdax-fetch-order-book-continuously.py │ ├── async-gdax-fetch-ticker-continuously.py │ ├── async-generator-basic.py │ ├── async-generator-multiple-tickers.py │ ├── async-generator-ticker-poller.py │ ├── async-instantiate-all-at-once.py │ ├── async-orderbooks-from-multiple-exchanges-at-once.py │ ├── async-theocean-orderbook.py │ ├── async-theocean-tickers.py │ ├── async-tickers-from-many-exchanges-at-once.py │ ├── async-tickers.py │ ├── async.py │ ├── balance-gdax.py │ ├── balance-kraken.py │ ├── balances.py │ ├── basic-chart.py │ ├── basic-rate-limiting.py │ ├── binance-fetch-ohlcv.py │ ├── binance-test-order.py │ ├── bitfinex-rate-limiting.py │ ├── bitmex-create-order.py │ ├── bitmex-fetch-ohlcv-with-extra-params.py │ ├── bitmex-ohlcv-convert-5m-to-15m.py │ ├── builtin-rate-limiting-long-poller.py │ ├── bypass-cloudflare-with-aiocfscrape.py │ ├── bypass-cloudflare-with-cookies.py │ ├── bypass-cloudflare.py │ ├── cli.py │ ├── cryptopia-fetch-order-books.py │ ├── exchanges.py │ ├── fetch-bitfinex-ohlcv-history.py │ ├── fetch-create-deposit-address.py │ ├── fetch-gdax-ohlcv-sequentially.py │ ├── fetch-ohlcv-cex.py │ ├── fetch-ohlcv-kraken.py │ ├── fetch-ohlcv-sequentially.py │ ├── fetch-okex-futures.py │ ├── fetch-orders.py │ ├── filter-words.py │ ├── gdax-fetch-my-trades-pagination.py │ ├── hitbtc2-withdraw.py │ ├── instantiate-all-at-once.py │ ├── manual-rate-limiting-long-poller.py │ ├── margin-leverage-order-kraken.py │ ├── minimal-2-lines.py │ ├── normalize-sparse-candle-timestamps.py │ ├── order-book-extra-level-depth-param.py │ ├── proxy-asyncio-aiohttp-python-3.py │ ├── proxy-sync-python-requests-2-and-3.py │ ├── record-future-history.py │ ├── study-trade.py │ ├── study1.py │ ├── symbols.py │ ├── test-server.py │ ├── tickers.py │ ├── triangle-trade-async.py │ ├── triangle-trade.py │ └── triangle.py ├── exchanges.cfg ├── export-exchanges.js ├── js ├── .eslintrc ├── _1broker.js ├── _1btcxe.js ├── acx.js ├── allcoin.js ├── anxpro.js ├── anybits.js ├── base │ ├── .eslintrc.js │ ├── Exchange.js │ ├── Market.js │ ├── errors.js │ ├── functions.js │ ├── functions │ │ ├── crypto.js │ │ ├── encode.js │ │ ├── generic.js │ │ ├── misc.js │ │ ├── number.js │ │ ├── orders.js │ │ ├── platform.js │ │ ├── string.js │ │ ├── throttle.js │ │ ├── time.js │ │ └── type.js │ └── journal.js ├── bcex.js ├── bibox.js ├── bigone.js ├── binance.js ├── bit2c.js ├── bitbank.js ├── bitbay.js ├── bitfinex.js ├── bitfinex2.js ├── bitflyer.js ├── bitforex.js ├── bithumb.js ├── bitkk.js ├── bitlish.js ├── bitmarket.js ├── bitmex.js ├── bitsane.js ├── bitso.js ├── bitstamp.js ├── bitstamp1.js ├── bittrex.js ├── bitz.js ├── bl3p.js ├── bleutrade.js ├── braziliex.js ├── btcalpha.js ├── btcbox.js ├── btcchina.js ├── btcexchange.js ├── btcmarkets.js ├── btctradeim.js ├── btctradeua.js ├── btcturk.js ├── btcx.js ├── bxinth.js ├── ccex.js ├── cex.js ├── chbtc.js ├── chilebit.js ├── cobinhood.js ├── coinbase.js ├── coinbaseprime.js ├── coinbasepro.js ├── coincheck.js ├── coinegg.js ├── coinex.js ├── coinexchange.js ├── coinfalcon.js ├── coinfloor.js ├── coingi.js ├── coinmarketcap.js ├── coinmate.js ├── coinnest.js ├── coinone.js ├── coinsecure.js ├── coinspot.js ├── cointiger.js ├── coolcoin.js ├── crypton.js ├── cryptopia.js ├── deribit.js ├── dsx.js ├── ethfinex.js ├── exmo.js ├── exx.js ├── fcoin.js ├── flowbtc.js ├── foxbit.js ├── fybse.js ├── fybsg.js ├── gatecoin.js ├── gateio.js ├── gdax.js ├── gemini.js ├── getbtc.js ├── hadax.js ├── hitbtc.js ├── hitbtc2.js ├── huobi.js ├── huobicny.js ├── huobipro.js ├── ice3x.js ├── independentreserve.js ├── indodax.js ├── itbit.js ├── jubi.js ├── kraken.js ├── kucoin.js ├── kuna.js ├── lakebtc.js ├── lbank.js ├── liqui.js ├── liquid.js ├── livecoin.js ├── luno.js ├── lykke.js ├── mercado.js ├── mixcoins.js ├── negociecoins.js ├── nova.js ├── okcoincny.js ├── okcoinusd.js ├── okex.js ├── paymium.js ├── poloniex.js ├── qryptos.js ├── quadrigacx.js ├── quoinex.js ├── rightbtc.js ├── southxchange.js ├── surbitcoin.js ├── test │ ├── .eslintrc.js │ ├── Exchange │ │ ├── test.currency.js │ │ ├── test.fetchBalance.js │ │ ├── test.fetchClosedOrders.js │ │ ├── test.fetchCurrencies.js │ │ ├── test.fetchFundingFees.js │ │ ├── test.fetchL2OrderBook.js │ │ ├── test.fetchMarkets.js │ │ ├── test.fetchMyTrades.js │ │ ├── test.fetchOHLCV.js │ │ ├── test.fetchOpenOrders.js │ │ ├── test.fetchOrderBook.js │ │ ├── test.fetchOrderBooks.js │ │ ├── test.fetchOrders.js │ │ ├── test.fetchTicker.js │ │ ├── test.fetchTickers.js │ │ ├── test.fetchTrades.js │ │ ├── test.fetchTradingFees.js │ │ ├── test.market.js │ │ ├── test.order.js │ │ ├── test.orderbook.js │ │ ├── test.ticker.js │ │ ├── test.trade.js │ │ └── tmp.test.fetchOHLCV.js │ ├── base │ │ ├── .eslintrc │ │ ├── functions │ │ │ ├── test.datetime.js │ │ │ ├── test.generic.js │ │ │ ├── test.number.js │ │ │ ├── test.time.js │ │ │ └── test.type.js │ │ └── test.base.js │ ├── errors │ │ ├── test.InsufficientFunds.js │ │ ├── test.InvalidNonce.js │ │ ├── test.InvalidOrder.js │ │ └── test.OrderNotFound.js │ ├── test.js │ └── test.timeout_hang.js ├── theocean.js ├── therock.js ├── tidebit.js ├── tidex.js ├── uex.js ├── urdubit.js ├── vaultoro.js ├── vbtc.js ├── virwox.js ├── wex.js ├── xbtce.js ├── yobit.js ├── yunbi.js ├── zaif.js └── zb.js ├── keys.json ├── package.json ├── php ├── AccountSuspended.php ├── AddressPending.php ├── ArgumentsRequired.php ├── AuthenticationError.php ├── BadRequest.php ├── BadResponse.php ├── BaseError.php ├── CancelPending.php ├── DDoSProtection.php ├── Exchange.php ├── ExchangeError.php ├── ExchangeNotAvailable.php ├── InsufficientFunds.php ├── InvalidAddress.php ├── InvalidNonce.php ├── InvalidOrder.php ├── NetworkError.php ├── NotSupported.php ├── NullResponse.php ├── OrderImmediatelyFillable.php ├── OrderNotCached.php ├── OrderNotFillable.php ├── OrderNotFound.php ├── PermissionDenied.php ├── RequestTimeout.php ├── _1broker.php ├── _1btcxe.php ├── acx.php ├── allcoin.php ├── anxpro.php ├── anybits.php ├── bcex.php ├── bibox.php ├── bigone.php ├── binance.php ├── bit2c.php ├── bitbank.php ├── bitbay.php ├── bitfinex.php ├── bitfinex2.php ├── bitflyer.php ├── bitforex.php ├── bithumb.php ├── bitkk.php ├── bitlish.php ├── bitmarket.php ├── bitmex.php ├── bitsane.php ├── bitso.php ├── bitstamp.php ├── bitstamp1.php ├── bittrex.php ├── bitz.php ├── bl3p.php ├── bleutrade.php ├── braziliex.php ├── btcalpha.php ├── btcbox.php ├── btcchina.php ├── btcexchange.php ├── btcmarkets.php ├── btctradeim.php ├── btctradeua.php ├── btcturk.php ├── btcx.php ├── bxinth.php ├── ccex.php ├── cex.php ├── chbtc.php ├── chilebit.php ├── cobinhood.php ├── coinbase.php ├── coinbaseprime.php ├── coinbasepro.php ├── coincheck.php ├── coinegg.php ├── coinex.php ├── coinexchange.php ├── coinfalcon.php ├── coinfloor.php ├── coingi.php ├── coinmarketcap.php ├── coinmate.php ├── coinnest.php ├── coinone.php ├── coinsecure.php ├── coinspot.php ├── cointiger.php ├── coolcoin.php ├── crypton.php ├── cryptopia.php ├── deribit.php ├── dsx.php ├── ethfinex.php ├── exmo.php ├── exx.php ├── fcoin.php ├── flowbtc.php ├── foxbit.php ├── fybse.php ├── fybsg.php ├── gatecoin.php ├── gateio.php ├── gdax.php ├── gemini.php ├── getbtc.php ├── hadax.php ├── hitbtc.php ├── hitbtc2.php ├── huobi.php ├── huobicny.php ├── huobipro.php ├── ice3x.php ├── independentreserve.php ├── indodax.php ├── itbit.php ├── jubi.php ├── kraken.php ├── kucoin.php ├── kuna.php ├── lakebtc.php ├── lbank.php ├── liqui.php ├── liquid.php ├── livecoin.php ├── luno.php ├── lykke.php ├── mercado.php ├── mixcoins.php ├── negociecoins.php ├── nova.php ├── okcoincny.php ├── okcoinusd.php ├── okex.php ├── paymium.php ├── poloniex.php ├── qryptos.php ├── quadrigacx.php ├── quoinex.php ├── rightbtc.php ├── southxchange.php ├── surbitcoin.php ├── test │ ├── ExchangeTest.php │ ├── bootstrap.php │ ├── decimal_to_precision.php │ ├── syntax.php │ ├── test.php │ └── test_exchange_datetime_functions.php ├── theocean.php ├── therock.php ├── tidebit.php ├── tidex.php ├── uex.php ├── urdubit.php ├── vaultoro.php ├── vbtc.php ├── virwox.php ├── wex.php ├── xbtce.php ├── yobit.php ├── yunbi.php ├── zaif.php └── zb.php ├── phpunit.xml.dist ├── postinstall.js ├── push-wiki.sh ├── push.sh ├── python ├── MANIFEST.in ├── README.rst ├── ccxt │ ├── _1broker.py │ ├── _1btcxe.py │ ├── __init__.py │ ├── acx.py │ ├── allcoin.py │ ├── anxpro.py │ ├── anybits.py │ ├── async_support │ │ ├── _1broker.py │ │ ├── _1btcxe.py │ │ ├── __init__.py │ │ ├── acx.py │ │ ├── allcoin.py │ │ ├── anxpro.py │ │ ├── anybits.py │ │ ├── base │ │ │ ├── __init__.py │ │ │ ├── exchange.py │ │ │ └── throttle.py │ │ ├── bcex.py │ │ ├── bibox.py │ │ ├── bigone.py │ │ ├── binance.py │ │ ├── bit2c.py │ │ ├── bitbank.py │ │ ├── bitbay.py │ │ ├── bitfinex.py │ │ ├── bitfinex2.py │ │ ├── bitflyer.py │ │ ├── bitforex.py │ │ ├── bithumb.py │ │ ├── bitkk.py │ │ ├── bitlish.py │ │ ├── bitmarket.py │ │ ├── bitmex.py │ │ ├── bitsane.py │ │ ├── bitso.py │ │ ├── bitstamp.py │ │ ├── bitstamp1.py │ │ ├── bittrex.py │ │ ├── bitz.py │ │ ├── bl3p.py │ │ ├── bleutrade.py │ │ ├── braziliex.py │ │ ├── btcalpha.py │ │ ├── btcbox.py │ │ ├── btcchina.py │ │ ├── btcexchange.py │ │ ├── btcmarkets.py │ │ ├── btctradeim.py │ │ ├── btctradeua.py │ │ ├── btcturk.py │ │ ├── btcx.py │ │ ├── bxinth.py │ │ ├── ccex.py │ │ ├── cex.py │ │ ├── chbtc.py │ │ ├── chilebit.py │ │ ├── cobinhood.py │ │ ├── coinbase.py │ │ ├── coinbaseprime.py │ │ ├── coinbasepro.py │ │ ├── coincheck.py │ │ ├── coinegg.py │ │ ├── coinex.py │ │ ├── coinexchange.py │ │ ├── coinfalcon.py │ │ ├── coinfloor.py │ │ ├── coingi.py │ │ ├── coinmarketcap.py │ │ ├── coinmate.py │ │ ├── coinnest.py │ │ ├── coinone.py │ │ ├── coinsecure.py │ │ ├── coinspot.py │ │ ├── cointiger.py │ │ ├── coolcoin.py │ │ ├── crypton.py │ │ ├── cryptopia.py │ │ ├── deribit.py │ │ ├── dsx.py │ │ ├── ethfinex.py │ │ ├── exmo.py │ │ ├── exx.py │ │ ├── fcoin.py │ │ ├── flowbtc.py │ │ ├── foxbit.py │ │ ├── fybse.py │ │ ├── fybsg.py │ │ ├── gatecoin.py │ │ ├── gateio.py │ │ ├── gdax.py │ │ ├── gemini.py │ │ ├── getbtc.py │ │ ├── hadax.py │ │ ├── hitbtc.py │ │ ├── hitbtc2.py │ │ ├── huobi.py │ │ ├── huobicny.py │ │ ├── huobipro.py │ │ ├── ice3x.py │ │ ├── independentreserve.py │ │ ├── indodax.py │ │ ├── itbit.py │ │ ├── jubi.py │ │ ├── kraken.py │ │ ├── kucoin.py │ │ ├── kuna.py │ │ ├── lakebtc.py │ │ ├── lbank.py │ │ ├── liqui.py │ │ ├── liquid.py │ │ ├── livecoin.py │ │ ├── luno.py │ │ ├── lykke.py │ │ ├── mercado.py │ │ ├── mixcoins.py │ │ ├── negociecoins.py │ │ ├── nova.py │ │ ├── okcoincny.py │ │ ├── okcoinusd.py │ │ ├── okex.py │ │ ├── paymium.py │ │ ├── poloniex.py │ │ ├── qryptos.py │ │ ├── quadrigacx.py │ │ ├── quoinex.py │ │ ├── rightbtc.py │ │ ├── southxchange.py │ │ ├── surbitcoin.py │ │ ├── theocean.py │ │ ├── therock.py │ │ ├── tidebit.py │ │ ├── tidex.py │ │ ├── uex.py │ │ ├── urdubit.py │ │ ├── vaultoro.py │ │ ├── vbtc.py │ │ ├── virwox.py │ │ ├── wex.py │ │ ├── xbtce.py │ │ ├── yobit.py │ │ ├── yunbi.py │ │ ├── zaif.py │ │ └── zb.py │ ├── base │ │ ├── __init__.py │ │ ├── decimal_to_precision.py │ │ ├── errors.py │ │ └── exchange.py │ ├── bcex.py │ ├── bibox.py │ ├── bigone.py │ ├── binance.py │ ├── bit2c.py │ ├── bitbank.py │ ├── bitbay.py │ ├── bitfinex.py │ ├── bitfinex2.py │ ├── bitflyer.py │ ├── bitforex.py │ ├── bithumb.py │ ├── bitkk.py │ ├── bitlish.py │ ├── bitmarket.py │ ├── bitmex.py │ ├── bitsane.py │ ├── bitso.py │ ├── bitstamp.py │ ├── bitstamp1.py │ ├── bittrex.py │ ├── bitz.py │ ├── bl3p.py │ ├── bleutrade.py │ ├── braziliex.py │ ├── btcalpha.py │ ├── btcbox.py │ ├── btcchina.py │ ├── btcexchange.py │ ├── btcmarkets.py │ ├── btctradeim.py │ ├── btctradeua.py │ ├── btcturk.py │ ├── btcx.py │ ├── bxinth.py │ ├── ccex.py │ ├── cex.py │ ├── chbtc.py │ ├── chilebit.py │ ├── cobinhood.py │ ├── coinbase.py │ ├── coinbaseprime.py │ ├── coinbasepro.py │ ├── coincheck.py │ ├── coinegg.py │ ├── coinex.py │ ├── coinexchange.py │ ├── coinfalcon.py │ ├── coinfloor.py │ ├── coingi.py │ ├── coinmarketcap.py │ ├── coinmate.py │ ├── coinnest.py │ ├── coinone.py │ ├── coinsecure.py │ ├── coinspot.py │ ├── cointiger.py │ ├── coolcoin.py │ ├── crypton.py │ ├── cryptopia.py │ ├── deribit.py │ ├── dsx.py │ ├── ethfinex.py │ ├── exmo.py │ ├── exx.py │ ├── fcoin.py │ ├── flowbtc.py │ ├── foxbit.py │ ├── fybse.py │ ├── fybsg.py │ ├── gatecoin.py │ ├── gateio.py │ ├── gdax.py │ ├── gemini.py │ ├── getbtc.py │ ├── hadax.py │ ├── hitbtc.py │ ├── hitbtc2.py │ ├── huobi.py │ ├── huobicny.py │ ├── huobipro.py │ ├── ice3x.py │ ├── independentreserve.py │ ├── indodax.py │ ├── itbit.py │ ├── jubi.py │ ├── kraken.py │ ├── kucoin.py │ ├── kuna.py │ ├── lakebtc.py │ ├── lbank.py │ ├── liqui.py │ ├── liquid.py │ ├── livecoin.py │ ├── luno.py │ ├── lykke.py │ ├── mercado.py │ ├── mixcoins.py │ ├── negociecoins.py │ ├── nova.py │ ├── okcoincny.py │ ├── okcoinusd.py │ ├── okex.py │ ├── paymium.py │ ├── poloniex.py │ ├── qryptos.py │ ├── quadrigacx.py │ ├── quoinex.py │ ├── rightbtc.py │ ├── southxchange.py │ ├── surbitcoin.py │ ├── theocean.py │ ├── therock.py │ ├── tidebit.py │ ├── tidex.py │ ├── uex.py │ ├── urdubit.py │ ├── vaultoro.py │ ├── vbtc.py │ ├── virwox.py │ ├── wex.py │ ├── xbtce.py │ ├── yobit.py │ ├── yunbi.py │ ├── zaif.py │ └── zb.py ├── deploy.sh ├── setup.cfg ├── setup.py ├── test │ ├── test.py │ ├── test_async.py │ ├── test_calculate_fee.py │ ├── test_decimal_to_precision.py │ ├── test_deep_extend.py │ └── test_exchange_datetime_functions.py └── tox.ini ├── run-tests.js ├── setup.cfg ├── transpile.js ├── update-badges.js ├── vss.js └── wiki ├── Certification.md ├── Exchange-Markets-By-Country.md ├── Exchange-Markets.md ├── FAQ.md ├── Install.md ├── Manual.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.* text eol=lf 2 | ccxt/exchanges.py linguis-generated=true 3 | ccxt/async/exchanges.py linguist-generated=true 4 | ccxt/async/__init__.py linguist-generated=false 5 | ccxt/async/exchange.py linguist-generated=false 6 | ccxt/__init__.py linguist-generated=false 7 | ccxt/errors.py linguist-generated=false 8 | ccxt/exchange.py linguist-generated=false 9 | ccxt/version.py linguist-generated=false 10 | ccxt.js linguist-generated=false 11 | ccxt.php linguist-generated=false 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # You shouldn't edit these files, as they're generated automatically from ccxt.js by build scripts. 3 | # Please read https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#multilanguage-support for details. 4 | # 5 | .vscode 6 | build/* 7 | node_modules/ 8 | npm-debug.log 9 | .DS_Store 10 | config.js 11 | config.py 12 | config.php 13 | dist/ 14 | ccxt.egg-info/ 15 | tmp/ 16 | *.pyc 17 | .tox/ 18 | coverage 19 | .nyc_output 20 | travis-keys.sh 21 | ccxt.wiki/ 22 | package-lock.json 23 | exchanges.json 24 | ccxt.sublime-workspace 25 | .idea 26 | yarn.lock 27 | keys.local.json 28 | nbproject/ 29 | vendor/ 30 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | ccxt.egg-info/ 2 | ccxt.wiki/ 3 | dist/ 4 | examples/php/ 5 | examples/py/ 6 | node_modules/ 7 | python/ 8 | php/ 9 | tmp/ 10 | .tox/ 11 | .DS_Store 12 | .nyc_output 13 | *.php 14 | *.py 15 | *.pyc 16 | ccxt.sublime-workspace 17 | composer.* 18 | config.js 19 | convert-md-2-rst 20 | coverage 21 | exchanges.json 22 | ISSUE_TEMPLATE.md 23 | keys.local.json 24 | npm-debug.log 25 | package-lock.json 26 | travis-keys.sh 27 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ATTENTION!!! 2 | 3 | MUST READ THIS BEFORE SUBMITTING ISSUES: 4 | 5 | https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-submit-an-issue 6 | 7 | - OS: 8 | - Programming Language version: 9 | - CCXT version: 10 | - Exchange: 11 | - Method: 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Igor Kroitor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ccxt.browser.js: -------------------------------------------------------------------------------- 1 | /* A entry point for the browser bundle version. This gets compiled by: 2 | 3 | browserify --debug ./ccxt.browser.js > ./build/ccxt.browser.js 4 | */ 5 | 6 | window.ccxt = require ('./ccxt') -------------------------------------------------------------------------------- /ccxt.php: -------------------------------------------------------------------------------- 1 | NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /examples/html/basic-cors-proxy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CCXT Basic example for the browser 5 | 6 | 29 | 30 | 31 |

Hello, CCXT!

32 |

33 | 
34 | 


--------------------------------------------------------------------------------
/examples/html/basic-inheritance.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     CCXT Basic example for the browser
 5 |     
 6 |     
10 |     
42 | 
43 | 
44 | 

Hello, CCXT!

45 |

46 | 
47 | 


--------------------------------------------------------------------------------
/examples/html/basic-rate-limiting.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     CCXT Basic example for the browser
 5 |     
 6 |     
44 | 
45 | 
46 | 

Hello, CCXT!

47 |

48 | 
49 | 


--------------------------------------------------------------------------------
/examples/html/basic.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     CCXT Basic example for the browser
 5 |     
 6 |     
38 | 
39 | 
40 | 

Hello, CCXT!

41 |

42 | 
43 | 


--------------------------------------------------------------------------------
/examples/js/README.md:
--------------------------------------------------------------------------------
 1 | # CCXT JavaScript Examples
 2 | 
 3 | These examples might require the following super-useful high-quality Node.js modules by [xpl](https://github.com/xpl):
 4 | 
 5 | - [ansicolor](https://github.com/xpl/ansicolor): A quality JavaScript library for the ANSI color/style management ([ansicolor @ npm](https://npmjs.com/package/ansicolor))
 6 | - [as-table](https://github.com/xpl/as-table): A simple function that prints objects as ASCII tables ([as-table @ npm](https://npmjs.com/package/as-table))
 7 | - [ololog](https://github.com/xpl/ololog): Platform-agnostic logging with blackjack and hookers ([ololog @ npm](https://npmjs.com/package/ololog))
 8 | 
 9 | All of the modules above are installed with the ccxt library devDependencies by npm automatically.
10 | 
11 | To run the ccxt JavaScript examples from any folder type in console:
12 | 
13 | ```shell
14 | node path/to/example.js # substitute for actual filename here
15 | ```
16 | 


--------------------------------------------------------------------------------
/examples/js/basic-chart.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt       = require ('../../ccxt.js')
 4 | const asciichart = require ('asciichart')
 5 | const asTable    = require ('as-table')
 6 | const log        = require ('ololog').configure ({ locate: false })
 7 | 
 8 | require ('ansicolor').nice
 9 | 
10 | //-----------------------------------------------------------------------------
11 | 
12 | ;(async function main () {
13 | 
14 |     // experimental, not yet implemented for all exchanges
15 |     // your contributions are welcome ;)
16 | 
17 |     const index = 4 // [ timestamp, open, high, low, close, volume ]
18 |     const ohlcv = await new ccxt.okcoinusd ().fetchOHLCV ('BTC/USD', '15m')
19 |     const lastPrice = ohlcv[ohlcv.length - 1][index] // closing price
20 |     const series = ohlcv.map (x => x[index])         // closing price
21 |     const bitcoinRate = ('₿ = $' + lastPrice).green
22 |     const chart = asciichart.plot (series, { height: 15, padding: '            ' })
23 |     log.yellow ("\n" + chart, bitcoinRate, "\n")
24 |     process.exit ()
25 | 
26 | }) ()


--------------------------------------------------------------------------------
/examples/js/binance-fetch-ohlcv.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt       = require ('../../ccxt.js')
 4 | const asciichart = require ('asciichart')
 5 | const asTable    = require ('as-table')
 6 | const log        = require ('ololog').configure ({ locate: false })
 7 | 
 8 | require ('ansicolor').nice
 9 | 
10 | //-----------------------------------------------------------------------------
11 | 
12 | ;(async function main () {
13 | 
14 |     const index = 4 // [ timestamp, open, high, low, close, volume ]
15 | 
16 | 
17 |     const ohlcv = await new ccxt.binance ().fetchOHLCV ('BTC/USDT', '1h')
18 | 
19 | 
20 |     const lastPrice = ohlcv[ohlcv.length - 1][index] // closing price
21 |     const series = ohlcv.slice (-80).map (x => x[index])         // closing price
22 |     const bitcoinRate = ('₿ = $' + lastPrice).green
23 |     const chart = asciichart.plot (series, { height: 15, padding: '            ' })
24 |     log.yellow ("\n" + chart, bitcoinRate, "\n")
25 |     process.exit ()
26 | 
27 | }) ()


--------------------------------------------------------------------------------
/examples/js/binance-server-time.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | const log  = require ('ololog').configure ({ locate: false })
 4 | const ccxt = require('../../ccxt')
 5 | 
 6 | const binance = new ccxt['binance'] ()
 7 | const recvWindow = binance.security.recvWindow
 8 | const aheadWindow = 1000
 9 | 
10 | async function test () {
11 |     const localStartTime = Date.now ()
12 |     const { serverTime } = await binance.publicGetTime ()
13 |     const localFinishTime = Date.now ()
14 |     const estimatedLandingTime = (localFinishTime + localStartTime) / 2
15 | 
16 |     const diff = serverTime - estimatedLandingTime
17 | 
18 |     log (`request departure time:     ${binance.iso8601 (localStartTime)}`)
19 |     log (`response arrival time:      ${binance.iso8601 (localFinishTime)}`)
20 |     log (`server time:                ${binance.iso8601 (serverTime)}`)
21 |     log (`request landing time (est): ${binance.iso8601 (estimatedLandingTime)}, ${Math.abs (diff)} ms ${Math.sign (diff) > 0 ? 'behind' : 'ahead of'} server`)
22 |     log ('\n')
23 | 
24 |     if (diff < -aheadWindow) {
25 |         log.error.red (`your request will likely be rejected if local time is ahead of the server's time for more than ${aheadWindow} ms \n`)
26 |     }
27 | 
28 |     if (diff > recvWindow) {
29 |         log.error.red (`your request will likely be rejected if local time is behind server time for more than ${recvWindow} ms\n`)
30 |     }
31 | }
32 | 
33 | test ();
34 | 


--------------------------------------------------------------------------------
/examples/js/bitfinex-fetch-trades.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const ccxt = require ('../../ccxt.js')
 6 |     , log  = require ('ololog')
 7 |     , asTable = require ('as-table').configure ({ delimiter: ' | ' })
 8 | 
 9 | // ----------------------------------------------------------------------------
10 | 
11 | ;(async () => {
12 | 
13 |     const exchange = new ccxt.bitfinex ({
14 |         'verbose': process.argv.includes ('--verbose'),
15 |         'timeout': 60000,
16 |     })
17 | 
18 |     try {
19 | 
20 |         const response = await exchange.fetchTrades ('ETH/BTC', 1518983548636 - 2 * 24 * 60 * 60 * 1000)
21 |         log (asTable (response))
22 |         log (response.length.toString (), 'trades')
23 |         log.green ('Succeeded.')
24 | 
25 |     } catch (e) {
26 | 
27 |         log.dim ('--------------------------------------------------------')
28 |         log (e.constructor.name, e.message)
29 |         log.dim ('--------------------------------------------------------')
30 |         log.dim (exchange.last_http_response)
31 |         log.error ('Failed.')
32 |     }
33 | 
34 | }) ()


--------------------------------------------------------------------------------
/examples/js/bitfinex2-fetch-trades.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const ccxt = require ('../../ccxt.js')
 6 |     , log  = require ('ololog')
 7 |     , asTable = require ('as-table').configure ({ delimiter: ' | ' })
 8 | 
 9 | // ----------------------------------------------------------------------------
10 | 
11 | ;(async () => {
12 | 
13 |     const exchange = new ccxt.bitfinex2 ({
14 |         'verbose': process.argv.includes ('--verbose'),
15 |         'timeout': 60000,
16 |     })
17 | 
18 |     try {
19 | 
20 |         const response = await exchange.fetchTrades ('ETH/BTC', 1518983548636 - 2 * 24 * 60 * 60 * 1000)
21 |         log (asTable (response))
22 |         log (response.length.toString (), 'trades')
23 |         log.green ('Succeeded.')
24 | 
25 |     } catch (e) {
26 | 
27 |         log.dim ('--------------------------------------------------------')
28 |         log (e.constructor.name, e.message)
29 |         log.dim ('--------------------------------------------------------')
30 |         log.dim (exchange.last_http_response)
31 |         log.error ('Failed.')
32 |     }
33 | 
34 | }) ()


--------------------------------------------------------------------------------
/examples/js/bittrex-balance.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt      = require ('../../ccxt.js')
 4 | const asTable   = require ('as-table')
 5 | const log       = require ('ololog').configure ({ locate: false })
 6 | 
 7 | require ('ansicolor').nice
 8 | 
 9 | let sleep = (ms) => new Promise (resolve => setTimeout (resolve, ms))
10 | 
11 | ;(async () => {
12 | 
13 |     // instantiate the exchange
14 |     let exchange = new ccxt.bittrex  ({
15 |         "apiKey": "471b47a06c384e81b24072e9a8739064",
16 |         "secret": "694025686e9445589787e8ca212b4cff",
17 |     })
18 | 
19 | 
20 |     try {
21 | 
22 |         // fetch account balance from the exchange
23 |         let balance = await exchange.fetchBalance ()
24 | 
25 |         // output the result
26 |         log (exchange.name.green, 'balance', balance)
27 | 
28 |     } catch (e) {
29 | 
30 |         if (e instanceof ccxt.DDoSProtection || e.message.includes ('ECONNRESET')) {
31 |             log.bright.yellow ('[DDoS Protection] ' + e.message)
32 |         } else if (e instanceof ccxt.RequestTimeout) {
33 |             log.bright.yellow ('[Request Timeout] ' + e.message)
34 |         } else if (e instanceof ccxt.AuthenticationError) {
35 |             log.bright.yellow ('[Authentication Error] ' + e.message)
36 |         } else if (e instanceof ccxt.ExchangeNotAvailable) {
37 |             log.bright.yellow ('[Exchange Not Available Error] ' + e.message)
38 |         } else if (e instanceof ccxt.ExchangeError) {
39 |             log.bright.yellow ('[Exchange Error] ' + e.message)
40 |         } else if (e instanceof ccxt.NetworkError) {
41 |             log.bright.yellow ('[Network Error] ' + e.message)
42 |         } else {
43 |             throw e;
44 |         }
45 |     }
46 | 
47 | }) ()


--------------------------------------------------------------------------------
/examples/js/builtin-rate-limiting-rest-poller.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt    = require ('../../ccxt.js')
 4 | const log     = require ('ololog')
 5 | const ansi    = require ('ansicolor').nice
 6 | const asTable = require ('as-table')
 7 | 
 8 | const exchange = new ccxt.gdax ({ enableRateLimit: true })
 9 | const repeat   = 100
10 | 
11 | async function test (symbol) {
12 | 
13 |     for (let i = 0; i < repeat; i++) {
14 |         let ticker = await exchange.fetchTicker (symbol)
15 |         log (exchange.id.green, exchange.iso8601 (exchange.milliseconds ()), ticker['datetime'], symbol.green, ticker['last'])
16 |     }
17 | }
18 | 
19 | const concurrent = [
20 |     test ('BTC/USD'),
21 |     test ('ETH/BTC'),
22 |     test ('ETH/USD')
23 | ]
24 | 
25 | Promise.all (concurrent)


--------------------------------------------------------------------------------
/examples/js/bypass-cloudflare.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const cloudscraper = require ('cloudscraper')
 6 |     , ccxt         = require ('../../ccxt.js')
 7 | 
 8 | // ----------------------------------------------------------------------------
 9 | 
10 | const scrapeCloudflareHttpHeaderCookie = (url) =>
11 | 
12 | 	(new Promise ((resolve, reject) =>
13 | 
14 | 		(cloudscraper.get (url, function (error, response, body) {
15 | 
16 | 			if (error) {
17 | 
18 | 				reject (error)
19 | 
20 | 			} else {
21 | 
22 | 				resolve (response.request.headers)
23 | 			}
24 | 		}))
25 |     ))
26 | 
27 | // ----------------------------------------------------------------------------
28 | 
29 | ;(async () => {
30 | 
31 |     const exchange = new ccxt.braziliex ({
32 |         'verbose': process.argv.includes ('--verbose'),
33 |         'timeout': 60000,
34 |     })
35 | 
36 | 	exchange.headers = await scrapeCloudflareHttpHeaderCookie (exchange.urls.www)
37 | 
38 |     // console.log (exchange.headers)
39 | 
40 |     try {
41 | 
42 |         const response = await exchange.loadMarkets ()
43 |         console.log (response);
44 |         console.log ('Succeeded.')
45 | 
46 |     } catch (e) {
47 | 
48 |         console.log ('--------------------------------------------------------')
49 |         console.log (e.constructor.name, e.message)
50 |         console.log ('--------------------------------------------------------')
51 |         console.log (exchange.last_http_response)
52 |         console.log ('Failed.')
53 |     }
54 | 
55 | }) ()


--------------------------------------------------------------------------------
/examples/js/cors-proxy.js:
--------------------------------------------------------------------------------
1 | // JavaScript CORS Proxy
2 | // Save this in a file like cors.js and run with `node cors [port]`
3 | // It will listen for your requests on the port you pass in command line or port 8080 by default
4 | let port = (process.argv.length > 2) ? parseInt (process.argv[2]) : 4080 // default
5 | require ('cors-anywhere').createServer ().listen (port, 'localhost')
6 | 


--------------------------------------------------------------------------------
/examples/js/create-order-handle-errors.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const ccxt = require ('../../ccxt.js')
 6 | 
 7 | // ----------------------------------------------------------------------------
 8 | 
 9 | ;(async () => {
10 | 
11 |     const exchange = new ccxt.bittrex ({
12 |         'apiKey': 'YOUR_API_KEY',
13 |         'secret': 'YOUR_SECRET_KEY',
14 |         'verbose': false, // set to true to see more debugging output
15 |         'timeout': 60000,
16 |         'enableRateLimit': true, // add this
17 |     })
18 | 
19 |     // try to load markets first, retry on request timeouts until it succeeds:
20 | 
21 |     while (true) {
22 | 
23 |         try {
24 | 
25 |             await exchange.loadMarkets ();
26 |             break;
27 | 
28 |         } catch (e) {
29 | 
30 |             if (e instanceof ccxt.RequestTimeout)
31 |                 console.log (exchange.iso8601 (Date.now ()), e.constructor.name, e.message)
32 |         }
33 |     }
34 | 
35 |     const symbol = 'ETH/BTC'
36 |     const orderType = 'limit'
37 |     const side = 'sell'
38 |     const amount = 0.321;
39 |     const price = 0.123;
40 | 
41 |     // try just one attempt to create an order
42 | 
43 |     try {
44 | 
45 |         const response = await exchange.createOrder (symbol, orderType, side, amount, price);
46 |         console.log (response);
47 |         console.log ('Succeeded');
48 | 
49 |     } catch (e) {
50 | 
51 |         console.log (exchange.iso8601 (Date.now ()), e.constructor.name, e.message)
52 |         console.log ('Failed');
53 | 
54 |     }
55 | 
56 | }) ()
57 | 


--------------------------------------------------------------------------------
/examples/js/credentials.json:
--------------------------------------------------------------------------------
1 | {
2 |     "hitbtc":        { "apiKey": "b6aad581670b30fb25d1c91cdbe8ca5c", "secret": "fa394ced37a488f9b5826a2d9ce39ae3" },
3 |     "bitso":         { "apiKey": "xZnHRmdlgJ", "secret": "e156bb7f7ab3a831afbc7a80f7866b9e" },
4 |     "coincheck":     { "apiKey": "dCyzY2T6w0DFhaco", "secret": "JpI0eMmxfa0tEpk3X-dNwyclSASJkl-S" }
5 | }
6 | 


--------------------------------------------------------------------------------
/examples/js/cryptopia-fetch-order-books.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const cloudscraper = require ('cloudscraper')
 6 |     , ccxt         = require ('../../ccxt.js')
 7 | 
 8 | // ----------------------------------------------------------------------------
 9 | 
10 | ;(async () => {
11 | 
12 |     const exchange = new ccxt.cryptopia ({
13 |         'verbose': process.argv.includes ('--verbose'),
14 |         'timeout': 60000,
15 |     })
16 | 
17 |     try {
18 | 
19 |         const response = await exchange.fetchOrderBooks ([
20 |             'ETH/BTC',
21 |             'LTC/BTC',
22 |             'OMG/BTC',
23 |         ])
24 |         console.log (response);
25 |         console.log ('Succeeded.')
26 | 
27 |     } catch (e) {
28 | 
29 |         console.log ('--------------------------------------------------------')
30 |         console.log (e.constructor.name, e.message)
31 |         console.log ('--------------------------------------------------------')
32 |         console.log (exchange.last_http_response)
33 |         console.log ('Failed.')
34 |     }
35 | 
36 | }) ()


--------------------------------------------------------------------------------
/examples/js/custom-proxy-url.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt.js')
 4 | 
 5 | ;(async function main () {
 6 | 
 7 |     const kraken1 = new ccxt.kraken ({
 8 |         proxy: function (url) {
 9 |             return 'https://example.com/?url=' + encodeURIComponent (url)
10 |         },
11 |     })
12 | 
13 |     console.log (await kraken1.loadMarkets ())
14 | 
15 |     const kraken2 = new ccxt.kraken ({
16 |         proxy: function (url) {
17 |             return 'https://cors-anywhere.herokuapp.com/' + url
18 |         },
19 |     })
20 | 
21 |     console.log (await kraken2.loadMarkets ())
22 | 
23 | }) ()


--------------------------------------------------------------------------------
/examples/js/exchanges.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt      = require ('../../ccxt.js')
 4 | const countries = require ('../../countries.js')
 5 | const asTable   = require ('as-table')
 6 | const util      = require ('util')
 7 | const log       = require ('ololog').configure ({ locate: false })
 8 | 
 9 | require ('ansicolor').nice
10 | 
11 | process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
12 | process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })
13 | 
14 | let exchanges = {}
15 | 
16 | ccxt.exchanges.forEach (id => { exchanges[id] = new (ccxt)[id] () })
17 | 
18 | log ('The ccxt library supports', (ccxt.exchanges.length.toString ()).green, 'exchanges:')
19 | 
20 | var countryName = function (code) {
21 |     return ((countries[code] !== undefined) ? countries[code] : code)
22 | }
23 | 
24 | log (asTable.configure ({ delimiter: ' | ' }) (Object.values (exchanges).map (exchange => {
25 | 
26 |     let countries = Array.isArray (exchange.countries) ?
27 |         exchange.countries.map (countryName).join (', ') :
28 |         countryName (exchange.countries)
29 | 
30 |     let website = Array.isArray (exchange.urls.www) ? exchange.urls.www[0] : exchange.urls.www
31 | 
32 |     return {
33 |         id: exchange.id,
34 |         name: exchange.name,
35 |         url: website,
36 |         countries: countries,
37 |     }
38 | 
39 | })))
40 | 


--------------------------------------------------------------------------------
/examples/js/fetch-from-many-exchanges-simultaneously.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | const ccxt = require ('../../ccxt.js')
 4 | const log  = require ('ololog')
 5 | 
 6 | const symbol = 'ETH/BTC'
 7 | const exchanges = [ 'gdax', 'hitbtc2', 'poloniex' ]
 8 | 
 9 | ;(async () => {
10 | 
11 |     const result = await Promise.all (exchanges.map (async id => {
12 | 
13 |         const exchange = new ccxt[id] ({ 'enableRateLimit': true })
14 |         const ticker = await exchange.fetchTicker (symbol)
15 |         return exchange.extend ({ 'exchange': id }, ticker)
16 | 
17 |     }))
18 | 
19 |     log (result);
20 | 
21 | }) ()


--------------------------------------------------------------------------------
/examples/js/fetch-ohlcv-cex.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt       = require ('../../ccxt.js')
 4 | const asciichart = require ('asciichart')
 5 | const asTable    = require ('as-table')
 6 | const log        = require ('ololog').configure ({ locate: false })
 7 | 
 8 | require ('ansicolor').nice
 9 | 
10 | //-----------------------------------------------------------------------------
11 | 
12 | ;(async function main () {
13 | 
14 |     // experimental, not yet implemented for all exchanges
15 |     // your contributions are welcome ;)
16 | 
17 |     const index = 4 // [ timestamp, open, high, low, close, volume ]
18 |     const ohlcv = await new ccxt.cex ().fetchOHLCV ('BTC/USD', '1m')
19 |     const lastPrice = ohlcv[ohlcv.length - 1][index] // closing price
20 |     const series = ohlcv.slice (-80).map (x => x[index]) // closing price
21 |     const bitcoinRate = ('₿ = $' + lastPrice).green
22 |     const chart = asciichart.plot (series, { height: 15, padding: '            ' })
23 |     log.yellow ("\n" + chart, bitcoinRate, "\n")
24 |     process.exit ()
25 | 
26 | }) ()


--------------------------------------------------------------------------------
/examples/js/fetch-okex-futures.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt')
 4 | 
 5 | async function test () {
 6 | 
 7 |     const exchange = new ccxt.okex ()
 8 |     await exchange.loadMarkets ()
 9 | 
10 |     for (let symbol in exchange.markets) {
11 | 
12 |         const market = exchange.markets[symbol]
13 | 
14 |         if (market['future']) {
15 |             console.log ('----------------------------------------------------')
16 |             console.log (symbol, await exchange.fetchTicker (symbol))
17 |             await ccxt.sleep (exchange.rateLimit)
18 |         }
19 |     }
20 | }
21 | 
22 | test ()
23 | 


--------------------------------------------------------------------------------
/examples/js/fetch-orders.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt')
 4 | const asTable = require ('as-table')
 5 | const log = require ('ololog')
 6 | 
 7 | require ('ansicolor').nice
 8 | 
 9 | const exchange = new ccxt.bittrex ({
10 |     apiKey: "471b47a06c384e81b24072e9a8739064",
11 |     secret: "694025686e9445589787e8ca212b4cff",
12 |     enableRateLimit: true,
13 | })
14 | 
15 | async function test () {
16 | 
17 |     const orders = await exchange.fetchOrders ()
18 | 
19 |     log (asTable (orders.map (order => ccxt.omit (order, [ 'timestamp', 'info' ]))))
20 | 
21 |     const order = await exchange.fetchOrder (orders[0]['id'])
22 | 
23 |     log (order)
24 | }
25 | 
26 | test ()


--------------------------------------------------------------------------------
/examples/js/fetch-ticker-from-multiple-exchanges.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt.js')
 4 | 
 5 | ;(async () => {
 6 | 
 7 |     const exchanges = [
 8 |         'bittrex',
 9 |         'poloniex',
10 |     ]
11 | 
12 |     const symbol = 'BTC/USDT'
13 |     const tickers = {}
14 | 
15 |     await Promise.all (exchanges.map (exchangeId =>
16 | 
17 |         new Promise (async (resolve, reject) => {
18 | 
19 |             const exchange = new ccxt[exchangeId] ({ enableRateLimit: true })
20 | 
21 |             while (true) {
22 | 
23 |                 const ticker = await exchange.fetchTicker (symbol)
24 |                 tickers[exchangeId] = ticker
25 | 
26 |                 Object.keys (tickers).map (exchangeId => {
27 |                     const ticker = tickers[exchangeId]
28 |                     console.log (ticker['datetime'], exchangeId, ticker['bid'], ticker['ask'])
29 |                 })
30 |             }
31 | 
32 |         })
33 | 
34 |     ))
35 | 
36 | }) ()


--------------------------------------------------------------------------------
/examples/js/instantiate-all-at-once.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt')
 4 | 
 5 | async function test () {
 6 | 
 7 |     let exchanges = { 
 8 |         "bittrex": {
 9 |             "apiKey": "60f38a5818934fc08308778f94d3d8c4", 
10 |             "secret": "9d294ddb5b944403b58e5298653720c1",
11 |         },
12 |         "bitfinex": { 
13 |             "apiKey": "02YsRDRAFwqt9JXfFKPIEw82mgmNbZtfpwvt8q5WK5a", 
14 |             "secret": "IummLrCfcZ9d9NPEtMg6chCpO8hugCvsDIscNm1F3pE"
15 |         },
16 |     }
17 | 
18 |     let ids = ccxt.exchanges.filter (id => id in exchanges)
19 | 
20 |     await Promise.all (ids.map (async id => {
21 | 
22 |         console.log (exchanges[id])
23 | 
24 |         // // instantiate the exchange
25 |         let exchange = new ccxt[id] (exchanges[id])
26 |         console.log (exchange.id, exchange.apiKey)
27 |         exchanges[id] = exchange
28 | 
29 |         // load markets
30 |         await exchange.loadMarkets ()
31 |         console.log (exchange.id, 'loaded')
32 | 
33 |         // check the balance
34 |         if (exchange.apiKey) {
35 |             let balance = await exchange.fetchBalance ()
36 |             console.log (exchange.id, balance)
37 |         }
38 | 
39 |         return exchange
40 |     }))
41 | 
42 |     // when all of them are ready, do your other things
43 |     console.log ('Loaded exchanges:', ids.join (', '))
44 | }
45 | 
46 | test ()
47 | 


--------------------------------------------------------------------------------
/examples/js/instantiate-all-from-json.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt     = require ('../../ccxt')
 4 |     , settings = require ('./credentials.json')
 5 | 
 6 | const enableRateLimit = true
 7 | 
 8 | async function test () {
 9 | 
10 |     const ids = ccxt.exchanges.filter (id => id in settings)
11 | 
12 |     const exchanges = ccxt.indexBy (await Promise.all (ids.map (async id => {
13 | 
14 |         // instantiate the exchange
15 |         let exchange = new ccxt[id] (ccxt.extend ({ enableRateLimit }, settings[id]))
16 | 
17 |         // load markets
18 |         await exchange.loadMarkets ()
19 | 
20 |         // check the balance
21 |         if (exchange.apiKey) {
22 |             let balance = await exchange.fetchBalance ()
23 |             console.log (exchange.id, balance['free'])
24 |         }
25 | 
26 |         return exchange
27 |     })), 'id')
28 | 
29 |     // when all of them are ready, do your other things
30 |     console.log ('Loaded exchanges:', Object.keys (exchanges).join (', '))
31 | }
32 | 
33 | test ()
34 | 


--------------------------------------------------------------------------------
/examples/js/market-status-and-currency-status.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | const ccxt = require ('../../ccxt')
 4 |     , log = require ('ololog')
 5 |     , asTable = require ('as-table')
 6 | 
 7 | ;(async function main () {
 8 | 
 9 |     let kraken = new ccxt.kraken ({ enableRateLimit: true })
10 |     await kraken.loadMarkets ()
11 | 
12 |     const markets = Object.values (kraken.markets).map (market => ({
13 |         symbol: market.symbol,
14 |         active: market.active,
15 |     }))
16 | 
17 |     log.bright.green.noLocate ('Markets:')
18 |     log.green.noLocate (asTable (markets), '\n')
19 | 
20 |     const currencies = Object.values (kraken.currencies).map (currency => ({
21 |         code: currency.code,
22 |         active: currency.active,
23 |         status: currency.status,
24 |     }))
25 | 
26 |     log.bright.yellow.noLocate ('Currencies:')
27 |     log.yellow.noLocate (asTable (currencies))
28 | 
29 | }) ()
30 | 


--------------------------------------------------------------------------------
/examples/js/okex-fetch-ohlcv-since-limit.js:
--------------------------------------------------------------------------------
 1 | const ccxt = require ('../../ccxt.js')
 2 |     , log  = require ('ololog')
 3 |     , ansi = require ('ansicolor').nice
 4 | 
 5 | ;(async () => {
 6 | 
 7 |     const exchange = new ccxt['okex']()
 8 |     exchange.enableRateLimit = true
 9 | 
10 |     let limit = undefined
11 |     let symbol = 'BTC/USDT'
12 |     let interval = '15m'
13 | 
14 |     // enable either of the following two lines
15 |     exchange.options['warnOnFetchOHLCVLimitArgument'] = false
16 |     // limit = 3
17 | 
18 |     const dates = [
19 |         '2014-01-01T00:00:00', // okex did not exist then
20 |         '2016-02-01T00:00:00',
21 |         '2018-02-15T00:00:00',
22 |         '2018-02-25T00:00:00',
23 |         '2018-02-27T00:00:00',
24 |     ]
25 | 
26 |     const results = await Promise.all (dates.map (async date => {
27 |         since = exchange.parse8601 (date)
28 |         const ohlcv = await exchange.fetchOHLCV (symbol, interval, since, limit)
29 |         const fetchingFrom = date.green
30 |         const firstCandleDate = ohlcv.length ? exchange.iso8601 (ohlcv[0][0]).yellow : undefined
31 |         const lastCandleDate = ohlcv.length ? exchange.iso8601 (ohlcv[ohlcv.length - 1][0]).yellow : undefined
32 |         const count = ohlcv.length.toString ().red
33 |         return { fetchingFrom, firstCandleDate, lastCandleDate, count, ohlcv }
34 |     }))
35 | 
36 |     log (results)
37 | 
38 | }) ()
39 | 


--------------------------------------------------------------------------------
/examples/js/order-book-extra-level-depth-param.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | const ccxt = require ('../../ccxt')
 4 | const asTable = require ('as-table')
 5 | const log = require ('ololog')
 6 | 
 7 | require ('ansicolor').nice
 8 | 
 9 | ;(async function test () {
10 | 
11 |     const exchange = new ccxt.bitfinex ()
12 |     const limit = 5
13 |     const orders = await exchange.fetchOrderBook ('BTC/USD', limit, {
14 |         // this parameter is exchange-specific, all extra params have unique names per exchange
15 |         'group': 1, // 1 = orders are grouped by price, 0 = orders are separate
16 |     })
17 | 
18 |     log (orders)
19 | }) ()


--------------------------------------------------------------------------------
/examples/php/README.md:
--------------------------------------------------------------------------------
1 | # CCXT PHP Examples
2 | 
3 | To run PHP examples from any folder type in console:
4 | 
5 | ```shell
6 | php -f path/to/example.php # substitute for actual filename here
7 | ```


--------------------------------------------------------------------------------
/examples/php/basic-error-handling.php:
--------------------------------------------------------------------------------
 1 | fetch_ticker ('NONEXISTENT_SYMBOL');
16 |     var_dump ($result);
17 | 
18 | } catch (Exception $e) {
19 | 
20 |     // print it
21 |     echo $e->getMessage () . "\n";
22 | 
23 |     // save to $message (for whatever needs)
24 |     $message = $e->getMessage ();
25 | }
26 | 
27 | ?>
28 | 


--------------------------------------------------------------------------------
/examples/php/binance-cancel-order.php:
--------------------------------------------------------------------------------
 1 |  'YOUR_API_KEY', // ←------------ replace with your keys
11 |     'secret' => 'YOUR_SECRET',
12 |     'verbose' => true,
13 | ));
14 | 
15 | try {
16 | 
17 |     $orderId = 'xxxxxxxx'; // ←--------- replace with your order id
18 |     $symbol = 'XRP/BTC'; // ←--------- replace with your symbol
19 | 
20 |     $exchange->cancelOrder ($orderId, $symbol);
21 | 
22 | } catch (\ccxt\NetworkError $e) {
23 |     echo '[Network Error] ' . $e->getMessage () . "\n";
24 | } catch (\ccxt\ExchangeError $e) {
25 |     echo '[Exchange Error] ' . $e->getMessage () . "\n";
26 | } catch (Exception $e) {
27 |     echo '[Error] ' . $e->getMessage () . "\n";
28 | }
29 | 
30 | ?>


--------------------------------------------------------------------------------
/examples/php/binance-fetch-ticker.php:
--------------------------------------------------------------------------------
 1 |  true,
11 |     'timeout' => 30000,
12 | ));
13 | 
14 | try {
15 | 
16 |     $symbol = 'ETH/BTC';
17 |     $result = $exchange->fetch_ticker ($symbol);
18 | 
19 |     var_dump ($result);
20 | 
21 | } catch (\ccxt\NetworkError $e) {
22 |     echo '[Network Error] ' . $e->getMessage () . "\n";
23 | } catch (\ccxt\ExchangeError $e) {
24 |     echo '[Exchange Error] ' . $e->getMessage () . "\n";
25 | } catch (Exception $e) {
26 |     echo '[Error] ' . $e->getMessage () . "\n";
27 | }
28 | 
29 | ?>


--------------------------------------------------------------------------------
/examples/php/binance-fetch-tickers.php:
--------------------------------------------------------------------------------
 1 |  true, // for debugging
11 |     'timeout' => 30000,
12 | ));
13 | 
14 | try {
15 | 
16 |     // WARNING !!!
17 | 
18 |     // DO NOT CALL THIS MORE THAN ONCE IN 2 MINUTES OR YOU WILL GET BANNED BY BINANCE!
19 | 
20 |     // https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#limits
21 | 
22 |     $result = $exchange->fetch_tickers ();
23 | 
24 |     print_r ($result);
25 | 
26 | } catch (\ccxt\NetworkError $e) {
27 |     echo '[Network Error] ' . $e->getMessage () . "\n";
28 | } catch (\ccxt\ExchangeError $e) {
29 |     echo '[Exchange Error] ' . $e->getMessage () . "\n";
30 | } catch (Exception $e) {
31 |     echo '[Error] ' . $e->getMessage () . "\n";
32 | }
33 | 
34 | ?>


--------------------------------------------------------------------------------
/examples/php/bitfinex2-fetch-ohlcv-since-limit.php:
--------------------------------------------------------------------------------
 1 |  true));
12 | 
13 | // load all markets from the exchange
14 | $markets = $exchange->load_markets ();
15 | 
16 | function run ($exchange, $symbol, $timeframe, $since, $limit) {
17 |     $ohlcvs = $exchange->fetchOHLCV ($symbol, $timeframe, $since, $limit);
18 |     foreach ($ohlcvs as $v) {
19 |         printf ("%s O:%.8f H:%.8f L:%.8f C:%.8f V:%.8f\n", $exchange->iso8601 ($v[0]), $v[1], $v[2], $v[3], $v[4], $v[5]);
20 |     }
21 | }
22 | 
23 | printf ("--------------------------------------------------------------\n");
24 | run ($exchange, 'ETH/BTC', '1m', 1518842513569, 5);
25 | printf ("--------------------------------------------------------------\n");
26 | run ($exchange, 'ETH/BTC', '1m', 1518842513569, 10);
27 | printf ("--------------------------------------------------------------\n");
28 | 
29 | ?>


--------------------------------------------------------------------------------
/examples/php/bitfinex2-fetch-ohlcv.php:
--------------------------------------------------------------------------------
 1 |  true,
12 |     'rateLimit' => 12000,
13 | ));
14 | 
15 | // bitfinex2 breaks occasionally
16 | 
17 | for ($i = 0; $i < 1000; $i++) {
18 |     $ohlcv = $exchange->fetch_ohlcv ('BTC/USD', '1m');
19 |     print_r ($exchange->iso8601 ($ohlcv[0][0]) . "\t" . count($ohlcv) . "\n");
20 | }
21 | 
22 | ?>


--------------------------------------------------------------------------------
/examples/php/bitfinex2-fetch-trades-since.php:
--------------------------------------------------------------------------------
 1 | fetch_trades ('ETH/BTC', 1518983548636 - 2 * 24 * 60 * 60 * 1000);
17 | 
18 | foreach ($trades as $trade) {
19 |     echo $trade['datetime'] . "\n";
20 | }
21 | echo count ($trades) . " trades\n";
22 | 
23 | ?>


--------------------------------------------------------------------------------
/examples/php/bitmex-create-order.php:
--------------------------------------------------------------------------------
 1 |  'YOUR_API_KEY', // ←------------ replace with your keys
11 |     'secret' => 'YOUR_SECRET',
12 |     'enableRateLimit' => true,
13 | ));
14 | 
15 | $symbol = 'XBTM18'; // bitcoin contract according to bitmex futures coding
16 | $type = 'StopLimit'; // # or 'market', or 'Stop' or 'StopLimit'
17 | $side = 'sell'; // or 'buy'
18 | $amount = 1.0;
19 | $price = 6500.0; // or None
20 | 
21 | // extra params and overrides
22 | $params = array (
23 |     'stopPx' => 6000.0, // if needed
24 | );
25 | 
26 | $order = $exchange->create_order ($symbol, $type, $side, $amount, $price, $params);
27 | 
28 | print_r ($order);
29 | 


--------------------------------------------------------------------------------
/examples/php/built-in-rate-limiting-poller.php:
--------------------------------------------------------------------------------
 1 |  true,
12 | ));
13 | 
14 | $symbol = 'DOGE/BTC';
15 | 
16 | while (true) {
17 |     $order_book = $exchange->fetch_order_book ($symbol);
18 |     echo "----------------------------------------------------------------\n";
19 |     echo date ('c') . "\n";
20 |     echo count ($order_book['bids']) . " bids and " . count ($order_book['asks']) . " asks\n";
21 |     echo sprintf ("bid: %.8f ask: %.8f", $order_book['bids'][0][0], $order_book['asks'][0][0]) . "\n";
22 | }
23 | 


--------------------------------------------------------------------------------
/examples/php/error-handling-message.php:
--------------------------------------------------------------------------------
 1 |  'foo',
11 |     'secret' => 'bar',
12 | ));
13 | 
14 | $message = null;
15 | 
16 | try {
17 | 
18 |     $result = $exchange->fetch_balance ();
19 |     var_dump ($result);
20 | 
21 | // these catch-clauses are showing the proper way of handling the errors
22 | 
23 | } catch (\ccxt\AuthenticationError $e) {
24 | 
25 |     // handle authentication error here
26 | 
27 | } catch (\ccxt\NetworkError $e) {
28 | 
29 |     // your code to handle the network code and retries here
30 | 
31 | } catch (\ccxt\ExchangeError $e) {
32 | 
33 |     // your code to handle an exchange error
34 | 
35 | } catch (Exception $e) {
36 | 
37 |     // This is an example of how NOT TO DO error handling
38 |     // One should not rely on the message string contained in the exception
39 |     // If you want to access it, that might indicate a design error in your code.
40 |     // See: https://github.com/ccxt/ccxt/issues/3053
41 | 
42 |     $message = $e->getMessage ();
43 | 
44 |     if (preg_match ('/[a-z]+\s+(\{.+\})$/iu', $e->getMessage (), $matches)) {
45 |         $message = $matches[1];
46 |     }
47 | 
48 |     echo print_r ($message, true) . "\n";
49 | 
50 | }
51 | 
52 | ?>
53 | 


--------------------------------------------------------------------------------
/examples/php/huobi-fetch-balance.php:
--------------------------------------------------------------------------------
 1 |  'YOUR_API_KEY', // ←------------ replace with your keys
11 |     'secret' => 'YOUR_SECRET',
12 |     // 'verbose' => true, // uncomment if debug output is needed
13 | ));
14 | 
15 | try {
16 | 
17 |     $balance = $exchange->fetch_balance ();
18 |     var_dump ($balance);
19 | 
20 | } catch (\ccxt\NetworkError $e) {
21 |     echo '[Network Error] ' . $e->getMessage () . "\n";
22 | } catch (\ccxt\ExchangeError $e) {
23 |     echo '[Exchange Error] ' . $e->getMessage () . "\n";
24 | } catch (Exception $e) {
25 |     echo '[Error] ' . $e->getMessage () . "\n";
26 | }
27 | 
28 | ?>
29 | 


--------------------------------------------------------------------------------
/examples/php/kraken-query-ledgers.php:
--------------------------------------------------------------------------------
 1 |  'YOUR_API_KEY',
15 |     'secret' => 'YOUR_SECRET_KEY',
16 | ));
17 | 
18 | // get ledgers
19 | $ledgers = $exchange->privatePostLedgers ();
20 | 
21 | // get ledger ids
22 | $ids = array_keys ($ledgers['result']['ledger']);
23 | 
24 | // get ledger entries for ledger id
25 | $ledger_entries = $exchange->privatePostQueryLedgers (array (
26 |     'id' =>  $ids[0],
27 | ));
28 | 
29 | var_dump ($ledger_entries);
30 | 
31 | ?>


--------------------------------------------------------------------------------
/examples/php/load-all-at-once.php:
--------------------------------------------------------------------------------
 1 | id . "\n";
16 | 
17 |     try {
18 |         $markets = $exchange->load_markets ();
19 |         echo count (array_values ($exchange->markets)) . " markets: " .
20 |             implode (', ', array_slice ($exchange->symbols, 0, 5)) . "...\n";
21 |     } catch (\ccxt\RequestTimeout $e) {
22 |         echo '[Timeout Error] ' . $e->getMessage () . ' (ignoring)' . "\n";
23 |     } catch (\ccxt\DDoSProtection $e) {
24 |         echo '[DDoS Protection Error] ' . $e->getMessage () . ' (ignoring)' . "\n";
25 |     } catch (\ccxt\AuthenticationError $e) {
26 |         echo '[Authentication Error] ' . $e->getMessage () . ' (ignoring)' . "\n";
27 |     } catch (\ccxt\ExchangeNotAvailable $e) {
28 |         echo '[Exchange Not Available] ' . $e->getMessage () . ' (ignoring)' . "\n";
29 |     } catch (\ccxt\NotSupported $e) {
30 |         echo '[Not Supported] ' . $e->getMessage () . ' (ignoring)' . "\n";
31 |     } catch (\ccxt\NetworkError $e) {
32 |         echo '[Network Error] ' . $e->getMessage () . ' (ignoring)' . "\n";
33 |     } catch (\ccxt\ExchangeError $e) {
34 |         echo '[Exchange Error] ' . $e->getMessage () . ' (ignoring)' . "\n";
35 |     } catch (Exception $e) {
36 |         echo '[Error] ' . $e->getMessage () . "\n";
37 |     }
38 |     echo "\n";
39 | }
40 | 
41 | 
42 | ?>


--------------------------------------------------------------------------------
/examples/php/order-book-level-depth-extra-param.php:
--------------------------------------------------------------------------------
 1 | fetch_order_book ('BTC/USD', $limit));
14 | 
15 | 
16 | ?>


--------------------------------------------------------------------------------
/examples/php/react-eventloop-with-rate-limiting.php:
--------------------------------------------------------------------------------
 1 | fetch_order_book ($symbol);
20 |     echo "----------------------------------------------------------------\n";
21 |     echo date ('c') . "\n";
22 |     echo count ($order_book['bids']) . " bids and " . count ($order_book['asks']) . " asks\n";
23 |     echo sprintf ("bid: %.8f ask: %.8f", $order_book['bids'][0][0], $order_book['asks'][0][0]) . "\n";
24 | 
25 |     $loop->futureTick ($tick_function);
26 | };
27 | 
28 | $loop->futureTick ($tick_function);
29 | $loop->run ();


--------------------------------------------------------------------------------
/examples/php/trading-view.php:
--------------------------------------------------------------------------------
 1 |  true,
19 | ));
20 | 
21 | // OHLCV format by default
22 | $ohlcv = $exchange->fetch_ohlcv ($symbol);
23 | 
24 | // convert OHLCV → TradingView
25 | $trading_view = $exchange->convert_ohlcv_to_trading_view ($ohlcv);
26 | 
27 | // convert TradingView → OHCLV
28 | $restored_ohlcvs = $exchange->convert_trading_view_to_ohlcv ($trading_view);
29 | 
30 | print_r ($restored_ohlcvs);
31 | 
32 | ?>


--------------------------------------------------------------------------------
/examples/php/vaultoro-fetch-balance.php:
--------------------------------------------------------------------------------
 1 |  true, // for debugging
11 |     // 'timeout' => 30000,
12 |     "apiKey" => "CEwxqNb3GzixcrhzrPkn47JkdsDpff6z",
13 |     "secret" => "ZXRBWURDN3NSVFNJSmFIRHlOWUVfd1d6UjZwSFdiTGI=",
14 | ));
15 | 
16 | try {
17 | 
18 |     $result = $exchange->fetch_balance ();
19 | 
20 |     print_r ($result);
21 | 
22 | } catch (\ccxt\NetworkError $e) {
23 |     echo '[Network Error] ' . $e->getMessage () . "\n";
24 | } catch (\ccxt\ExchangeError $e) {
25 |     echo '[Exchange Error] ' . $e->getMessage () . "\n";
26 | } catch (Exception $e) {
27 |     echo '[Error] ' . $e->getMessage () . "\n";
28 | }
29 | 
30 | ?>


--------------------------------------------------------------------------------
/examples/py/README.md:
--------------------------------------------------------------------------------
 1 | # CCXT Python Examples
 2 | 
 3 | To run Python examples from any folder, type in console:
 4 | 
 5 | ```shell
 6 | python path/to/example.py # substitute for actual filename here
 7 | ```
 8 | 
 9 | Example files starting with `async-` require Python 3.6 with `async`/`await` and async generators support.
10 | 
11 | ![basic-chart](https://user-images.githubusercontent.com/1294454/29979754-6d62354c-8f4f-11e7-9e0a-22e87b4a093b.jpg)
12 | 
13 | ## See Also
14 | 
15 | [co3k-crypto-currency-note](https://github.com/co3k/co3k-crypto-currency-note/blob/master/Untitled.ipynb) – an example of using ccxt to fetch OHLCV candles from Kraken and charting them with matplotlib in a Jupyter Notebook, made by [co3k](https://github.com/co3k).
16 | 


--------------------------------------------------------------------------------
/examples/py/async-balance-gdax.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test():
14 |     gdax = ccxt.gdax({
15 |         'apiKey': "a43edfe629bc5991acc83a536ac6358e",
16 |         'secret': "xOvq+iH8NT07TheFB/fmY3GcnMZMwP7Xct9zwWtAZxsCbJh8rxeEe/0BGxfbV2em7P9iqQD7/TJGqmsDO8B/kw==",
17 |         'password': 'zdmj8o7byla',
18 |         'verbose': True,  # switch it to False if you don't want the HTTP log
19 |     })
20 |     # move gdax to sandbox
21 |     gdax.urls['api'] = 'https://api-public.sandbox.gdax.com'
22 |     print(await gdax.fetch_balance())
23 | 
24 | 
25 | asyncio.get_event_loop().run_until_complete(test())
26 | 


--------------------------------------------------------------------------------
/examples/py/async-balance.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test():
14 |     bittrex = ccxt.bittrex({
15 |         'apiKey': "c5af1d0ceeaa4729ad87da1b05d9dfc3",
16 |         'secret': "d055d8e47fdf4c3bbd0ec6c289ea8ffd",
17 |         'verbose': True,  # switch it to False if you don't want the HTTP log
18 |     })
19 |     print(await bittrex.fetch_balance())
20 | 
21 | 
22 | asyncio.get_event_loop().run_until_complete(test())
23 | 


--------------------------------------------------------------------------------
/examples/py/async-balances.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test(exchange):
14 |     print(await exchange.fetch_balance())
15 | 
16 | 
17 | kraken = ccxt.kraken({
18 |     'apiKey': "hEvQNMDIeoCJbr7W/ZBb5CGOrx3G0lWF5B3zqa1JBxdZlEaL8EK+D0Mw",
19 |     'secret': "JaE9wI6Nwgh5oRxiHcVxurwzwBxwc05W/qv/k1srGg4s3EYuXPpNkLLM5NYbbWpM8rCyijIeDavRuqWbU0ZV9A==",
20 |     'verbose': True,  # switch it to False if you don't want the HTTP log
21 | })
22 | bitfinex = ccxt.bitfinex({
23 |     'apiKey': "4FlEDtxDl35gdEiobnfZ72vJeZteE4Bb7JdvqzjIjHq",
24 |     'secret': "D4DXM8DZdHuAq9YptUsb42aWT1XBnGlIJgLi8a7tzFH",
25 |     'verbose': True,  # switch it to False if you don't want the HTTP log
26 | })
27 | 
28 | [asyncio.ensure_future(test(exchange)) for exchange in [kraken, bitfinex]]
29 | pending = asyncio.Task.all_tasks()
30 | loop = asyncio.get_event_loop()
31 | loop.run_until_complete(asyncio.gather(*pending))
32 | 


--------------------------------------------------------------------------------
/examples/py/async-basic-rate-limiter.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def main(exchange):
14 |     for i in range(0, 10):
15 |         # this can be any call instead of fetch_ticker, really
16 |         print(await exchange.fetch_ticker('BTC/USD'))
17 | 
18 | 
19 | # you can set enableRateLimit = True to enable the built-in rate limiter
20 | # this way you request rate will never hit the limit of an exchange
21 | # the library will throttle your requests to avoid that
22 | 
23 | exchange = ccxt.bitfinex({
24 |     'enableRateLimit': True,  # this option enables the built-in rate limiter
25 | })
26 | 
27 | asyncio.get_event_loop().run_until_complete(main(exchange))
28 | 


--------------------------------------------------------------------------------
/examples/py/async-basic.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test_gdax():
14 |     gdax = ccxt.gdax()
15 |     markets = await gdax.load_markets()
16 |     await gdax.close()
17 |     return markets
18 | 
19 | if __name__ == '__main__':
20 |     print(asyncio.get_event_loop().run_until_complete(test_gdax()))
21 | 


--------------------------------------------------------------------------------
/examples/py/async-bitfinex-private-post-account-infos.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test(exchange):
14 |     print(await exchange.private_post_account_infos())
15 | 
16 | 
17 | bitfinex = ccxt.bitfinex({
18 |     'apiKey': "4FlEDtxDl35gdEiobnfZ72vJeZteE4Bb7JdvqzjIjHq",
19 |     'secret': "D4DXM8DZdHuAq9YptUsb42aWT1XBnGlIJgLi8a7tzFH",
20 |     'verbose': True,  # switch it to False if you don't want the HTTP log
21 | })
22 | 
23 | [asyncio.ensure_future(test(exchange)) for exchange in [bitfinex]]
24 | pending = asyncio.Task.all_tasks()
25 | loop = asyncio.get_event_loop()
26 | loop.run_until_complete(asyncio.gather(*pending))
27 | 


--------------------------------------------------------------------------------
/examples/py/async-bitstamp-create-limit-buy-order.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def test():
14 | 
15 |     exchange = ccxt.bitstamp({
16 |         'apiKey': 'YOUR_API_KEY',
17 |         'secret': 'YOUR_SECRET',
18 |         'enableRateLimit': True,  # this is required, as documented in the Manual!
19 |     })
20 | 
21 |     response = None
22 | 
23 |     try:
24 | 
25 |         await exchange.load_markets()  # force-preload markets first
26 | 
27 |         exchange.verbose = True  # this is for debugging
28 | 
29 |         symbol = 'BTC/USD'  # change for your symbol
30 |         amount = 1.0        # change the amount
31 |         price = 6000.00     # change the price
32 | 
33 |         try:
34 | 
35 |             response = await exchange.create_limit_buy_order(symbol, amount, price)
36 | 
37 |         except Exception as e:
38 |             print('Failed to create order with', exchange.id, type(e).__name__, str(e))
39 | 
40 |     except Exception as e:
41 |         print('Failed to load markets from', exchange.id, type(e).__name__, str(e))
42 | 
43 |     await exchange.close()
44 |     return response
45 | 
46 | if __name__ == '__main__':
47 |     print(asyncio.get_event_loop().run_until_complete(test()))
48 | 


--------------------------------------------------------------------------------
/examples/py/async-bittrex-orderbook.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | if not sys.version >= '3.6':
 8 |     print('This script requires Python 3.6+')
 9 |     sys.exit()
10 | 
11 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
12 | sys.path.append(root + '/python')
13 | 
14 | import ccxt.async_support as ccxt  # noqa: E402
15 | 
16 | exchange = ccxt.bittrex()
17 | 
18 | 
19 | async def poll():
20 |     while True:
21 |         yield await exchange.fetch_order_book('BTC/USDT')
22 |         await asyncio.sleep(exchange.rateLimit / 1000)
23 | 
24 | 
25 | async def main():
26 |     async for orderbook in poll():
27 |         print(orderbook['bids'][0], orderbook['asks'][0])
28 | 
29 | 
30 | asyncio.get_event_loop().run_until_complete(main())
31 | 


--------------------------------------------------------------------------------
/examples/py/async-fetch-ticker.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | print(asyncio.get_event_loop().run_until_complete(ccxt.liqui().fetch_ticker('ETH/BTC')))
13 | 


--------------------------------------------------------------------------------
/examples/py/async-gdax-fetch-order-book-continuously.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | async def main(exchange, symbol):
14 |     while True:
15 |         print('--------------------------------------------------------------')
16 |         print(exchange.iso8601(exchange.milliseconds()), 'fetching', symbol, 'ticker from', exchange.name)
17 |         # this can be any call really
18 |         ticker = await exchange.fetch_order_book(symbol)
19 |         print(exchange.iso8601(exchange.milliseconds()), 'fetched', symbol, 'ticker from', exchange.name)
20 |         print(ticker)
21 | 
22 | 
23 | # you can set enableRateLimit = True to enable the built-in rate limiter
24 | # this way you request rate will never hit the limit of an exchange
25 | # the library will throttle your requests to avoid that
26 | 
27 | exchange = ccxt.gdax({
28 |     'enableRateLimit': True,  # this option enables the built-in rate limiter
29 | })
30 | 
31 | asyncio.get_event_loop().run_until_complete(main(exchange, 'LTC/USD'))
32 | 


--------------------------------------------------------------------------------
/examples/py/async-generator-basic.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | exchange = ccxt.poloniex({
13 |     'enableRateLimit': True,  # don't remove this line or they might ban you: https://github.com/ccxt/ccxt/wiki/Manual#rate-limit
14 | })
15 | 
16 | 
17 | async def poll():
18 |     while True:
19 |         yield await exchange.fetch_ticker('ETH/BTC')
20 | 
21 | 
22 | async def main():
23 |     async for ticker in poll():
24 |         print(ticker)
25 | 
26 | 
27 | asyncio.get_event_loop().run_until_complete(main())
28 | 


--------------------------------------------------------------------------------
/examples/py/async-generator-multiple-tickers.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import ccxt.async_support as ccxt
 5 | 
 6 | 
 7 | async def poll(tickers):
 8 |     i = 0
 9 |     kraken = ccxt.kraken()
10 |     while True:
11 |         symbol = tickers[i % len(tickers)]
12 |         yield (symbol, await kraken.fetch_ticker(symbol))
13 |         i += 1
14 |         await asyncio.sleep(kraken.rateLimit / 1000)
15 | 
16 | 
17 | async def main():
18 |     async for (symbol, ticker) in poll(['BTC/USD', 'ETH/BTC', 'BTC/EUR']):
19 |         print(symbol, ticker)
20 | 
21 | 
22 | asyncio.get_event_loop().run_until_complete(main())
23 | 


--------------------------------------------------------------------------------
/examples/py/async-generator-ticker-poller.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | kraken = ccxt.kraken({
13 |     'apiKey': "hEvQNMDIeoCJbr7W/ZBb5CGOrx3G0lWF5B3zqa1JBxdZlEaL8EK+D0Mw",
14 |     'secret': "JaE9wI6Nwgh5oRxiHcVxurwzwBxwc05W/qv/k1srGg4s3EYuXPpNkLLM5NYbbWpM8rCyijIeDavRuqWbU0ZV9A==",
15 |     # 'verbose': True, # switch it to False if you don't want the HTTP log
16 | })
17 | 
18 | 
19 | async def poll():
20 |     while True:
21 |         yield await kraken.fetch_ticker('BTC/USD')
22 |         await asyncio.sleep(kraken.rateLimit / 1000)
23 | 
24 | 
25 | async def main():
26 |     async for ticker in poll():
27 |         print(ticker)
28 | 
29 | 
30 | asyncio.get_event_loop().run_until_complete(main())
31 | 


--------------------------------------------------------------------------------
/examples/py/async-instantiate-all-at-once.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import asyncio
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | exchanges = {}  # a placeholder for your instances
13 | 
14 | for id in ccxt.exchanges:
15 |     exchange = getattr(ccxt, id)
16 |     exchanges[id] = exchange()
17 | 
18 | # now exchanges dictionary contains all exchange instances...
19 | asyncio.get_event_loop().run_until_complete(exchanges['bittrex'].fetch_order_book('ETH/BTC'))
20 | 


--------------------------------------------------------------------------------
/examples/py/async-theocean-orderbook.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | if not sys.version >= '3.6':
 8 |     print('This script requires Python 3.6+')
 9 |     sys.exit()
10 | 
11 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
12 | sys.path.append(root + '/python')
13 | 
14 | import ccxt.async_support as ccxt  # noqa: E402
15 | 
16 | exchange = ccxt.theocean()
17 | 
18 | 
19 | async def poll():
20 |     while True:
21 |         yield await exchange.fetch_order_book('WETH/TUSD')
22 |         await asyncio.sleep(exchange.rateLimit / 1000)
23 | 
24 | 
25 | async def main():
26 |     async for orderbook in poll():
27 |         print(orderbook['bids'][0], orderbook['asks'][0])
28 | 
29 | 
30 | asyncio.get_event_loop().run_until_complete(main())
31 | 


--------------------------------------------------------------------------------
/examples/py/async-theocean-tickers.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | def get_active_symbols(exchange):
14 |     return [symbol for symbol in exchange.symbols if is_active_symbol(exchange, symbol)]
15 | 
16 | 
17 | def is_active_symbol(exchange, symbol):
18 |     return ('.' not in symbol) and (('active' not in exchange.markets[symbol]) or (exchange.markets[symbol]['active']))
19 | 
20 | 
21 | async def fetch_ticker(exchange, symbol):
22 |     ticker = await exchange.fetchTicker(symbol)
23 |     print(exchange.id, symbol, ticker)
24 |     return ticker
25 | 
26 | 
27 | async def fetch_tickers(exchange):
28 |     await exchange.load_markets()
29 |     print(exchange.id, 'fetching all tickers by simultaneous multiple concurrent requests')
30 |     symbols_to_load = get_active_symbols(exchange)
31 |     input_coroutines = [fetch_ticker(exchange, symbol) for symbol in symbols_to_load]
32 |     tickers = await asyncio.gather(*input_coroutines, return_exceptions=True)
33 |     for ticker, symbol in zip(tickers, symbols_to_load):
34 |         if not isinstance(ticker, dict):
35 |             print(exchange.id, symbol, 'error')
36 |         else:
37 |             print(exchange.id, symbol, 'ok')
38 |     print(exchange.id, 'fetched', len(list(tickers)), 'tickers')
39 |     await exchange.close()
40 | 
41 | 
42 | asyncio.get_event_loop().run_until_complete(fetch_tickers(ccxt.theocean({
43 |     'enableRateLimit': True,  # this option enables the built-in rate limiter
44 | })))
45 | 


--------------------------------------------------------------------------------
/examples/py/async-tickers-from-many-exchanges-at-once.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import ccxt
 5 | import ccxt.async_support as ccxta  # noqa: E402
 6 | import time
 7 | import os
 8 | import sys
 9 | 
10 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
11 | sys.path.append(root + '/python')
12 | 
13 | 
14 | def sync_client(exchange):
15 |     client = getattr(ccxt, exchange)()
16 |     tickers = client.fetch_tickers()
17 |     return tickers
18 | 
19 | 
20 | async def async_client(exchange):
21 |     client = getattr(ccxta, exchange)()
22 |     tickers = await client.fetch_tickers()
23 |     await client.close()
24 |     return tickers
25 | 
26 | 
27 | async def multi_tickers(exchanges):
28 |     input_coroutines = [async_client(exchange) for exchange in exchanges]
29 |     tickers = await asyncio.gather(*input_coroutines, return_exceptions=True)
30 |     return tickers
31 | 
32 | 
33 | if __name__ == '__main__':
34 | 
35 |     # Consider review request rate limit in the methods you call
36 |     exchanges = ["coinex", "bittrex", "bitfinex", "poloniex", "hitbtc"]
37 | 
38 |     tic = time.time()
39 |     a = asyncio.get_event_loop().run_until_complete(multi_tickers(exchanges))
40 |     print("async call spend:", time.time() - tic)
41 | 
42 |     time.sleep(1)
43 | 
44 |     tic = time.time()
45 |     a = [sync_client(exchange) for exchange in exchanges]
46 |     print("sync call spend:", time.time() - tic)
47 | 


--------------------------------------------------------------------------------
/examples/py/async-tickers.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt.async_support as ccxt  # noqa: E402
11 | 
12 | 
13 | def get_active_symbols(exchange):
14 |     return [symbol for symbol in exchange.symbols if is_active_symbol(exchange, symbol)]
15 | 
16 | 
17 | def is_active_symbol(exchange, symbol):
18 |     return ('.' not in symbol) and (('active' not in exchange.markets[symbol]) or (exchange.markets[symbol]['active']))
19 | 
20 | 
21 | async def fetch_ticker(exchange, symbol):
22 |     ticker = await exchange.fetchTicker(symbol)
23 |     print(exchange.id, symbol, ticker)
24 |     return ticker
25 | 
26 | 
27 | async def fetch_tickers(exchange):
28 |     await exchange.load_markets()
29 |     print(exchange.id, 'fetching all tickers by simultaneous multiple concurrent requests')
30 |     symbols_to_load = get_active_symbols(exchange)
31 |     input_coroutines = [fetch_ticker(exchange, symbol) for symbol in symbols_to_load]
32 |     tickers = await asyncio.gather(*input_coroutines, return_exceptions=True)
33 |     for ticker, symbol in zip(tickers, symbols_to_load):
34 |         if not isinstance(ticker, dict):
35 |             print(exchange.id, symbol, 'error')
36 |         else:
37 |             print(exchange.id, symbol, 'ok')
38 |     print(exchange.id, 'fetched', len(list(tickers)), 'tickers')
39 | 
40 | 
41 | asyncio.get_event_loop().run_until_complete(fetch_tickers(ccxt.bitfinex({
42 |     'enableRateLimit': True,  # this option enables the built-in rate limiter
43 | })))
44 | 


--------------------------------------------------------------------------------
/examples/py/async.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import asyncio
 4 | import functools
 5 | import os
 6 | import sys
 7 | 
 8 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 9 | sys.path.append(root + '/python')
10 | 
11 | import ccxt.async_support as ccxt  # noqa: E402
12 | 
13 | 
14 | async def print_ticker(symbol, id):
15 |     # verbose mode will show the order of execution to verify concurrency
16 |     exchange = getattr(ccxt, id)({'verbose': True})
17 |     print(await exchange.fetch_ticker(symbol))
18 | 
19 | 
20 | if __name__ == '__main__':
21 | 
22 |     symbol = 'ETH/BTC'
23 |     print_ethbtc_ticker = functools.partial(print_ticker, symbol)
24 |     [asyncio.ensure_future(print_ethbtc_ticker(id)) for id in [
25 |         'bitfinex',
26 |         'poloniex',
27 |         'kraken',
28 |         'gdax',
29 |         'bittrex',
30 |         'hitbtc',
31 |     ]]
32 |     pending = asyncio.Task.all_tasks()
33 |     loop = asyncio.get_event_loop()
34 |     loop.run_until_complete(asyncio.gather(*pending))
35 | 


--------------------------------------------------------------------------------
/examples/py/balance-gdax.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | gdax = ccxt.gdax({
12 |     'apiKey': "a43edfe629bc5991acc83a536ac6358e",
13 |     'secret': "xOvq+iH8NT07TheFB/fmY3GcnMZMwP7Xct9zwWtAZxsCbJh8rxeEe/0BGxfbV2em7P9iqQD7/TJGqmsDO8B/kw==",
14 |     'password': 'zdmj8o7byla',
15 |     'verbose': True,  # switch it to False if you don't want the HTTP log
16 | })
17 | 
18 | # move gdax to sandbox
19 | gdax.urls['api'] = 'https://api-public.sandbox.gdax.com'
20 | 
21 | print(gdax.fetch_balance())
22 | 


--------------------------------------------------------------------------------
/examples/py/balance-kraken.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | kraken = ccxt.kraken({
12 |     'apiKey': "hEvQNMDIeoCJbr7W/ZBb5CGOrx3G0lWF5B3zqa1JBxdZlEaL8EK+D0Mw",
13 |     'secret': "JaE9wI6Nwgh5oRxiHcVxurwzwBxwc05W/qv/k1srGg4s3EYuXPpNkLLM5NYbbWpM8rCyijIeDavRuqWbU0ZV9A==",
14 |     'verbose': True,  # switch it to False if you don't want the HTTP log
15 | })
16 | 
17 | print(kraken.fetch_balance())
18 | 


--------------------------------------------------------------------------------
/examples/py/basic-chart.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import asciichart
 6 | 
 7 | # -----------------------------------------------------------------------------
 8 | 
 9 | this_folder = os.path.dirname(os.path.abspath(__file__))
10 | root_folder = os.path.dirname(os.path.dirname(this_folder))
11 | sys.path.append(root_folder + '/python')
12 | sys.path.append(this_folder)
13 | 
14 | # -----------------------------------------------------------------------------
15 | 
16 | import ccxt  # noqa: E402
17 | 
18 | # -----------------------------------------------------------------------------
19 | 
20 | kraken = ccxt.kraken()
21 | gdax = ccxt.gdax()
22 | 
23 | symbol = 'BTC/USD'
24 | 
25 | # each ohlcv candle is a list of [ timestamp, open, high, low, close, volume ]
26 | index = 4  # use close price from each ohlcv candle
27 | 
28 | 
29 | def print_chart(exchange, symbol, timeframe):
30 | 
31 |     print("\n" + exchange.name + ' ' + symbol + ' ' + timeframe + ' chart:')
32 | 
33 |     # get a list of ohlcv candles
34 |     ohlcv = exchange.fetch_ohlcv(symbol, timeframe)
35 | 
36 |     # get the ohlCv (closing price, index == 4)
37 |     series = [x[index] for x in ohlcv]
38 | 
39 |     # print the chart
40 |     print("\n" + asciichart.plot(series[-120:], {'height': 20}))  # print the chart
41 | 
42 |     last = ohlcv[len(ohlcv) - 1][index]  # last closing price
43 |     return last
44 | 
45 | 
46 | last = print_chart(kraken, 'BTC/USD', '1h')
47 | print("\n" + kraken.name + " ₿ = $" + str(last) + "\n")  # print last closing price
48 | 
49 | last = print_chart(gdax, 'BTC/USD', '1h')
50 | print("\n" + gdax.name + " ₿ = $" + str(last) + "\n")  # print last closing price
51 | 


--------------------------------------------------------------------------------
/examples/py/basic-rate-limiting.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | from pprint import pprint
 4 | 
 5 | import os
 6 | import sys
 7 | 
 8 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 9 | sys.path.append(root + '/python')
10 | 
11 | import ccxt  # noqa: E402
12 | 
13 | 
14 | symbol = 'ETH/BTC'
15 | 
16 | exchange = ccxt.poloniex({
17 |     'enableRateLimit': True,  # or .enableRateLimit = True later
18 | })
19 | 
20 | # print 10 times with appropriate delay
21 | for i in range(0, 10):
22 |     print('--------------------------------------------------------------------')
23 |     ticker = exchange.fetch_ticker(symbol)
24 |     ticker = exchange.omit(ticker, 'info')
25 |     pprint(ticker)
26 | 


--------------------------------------------------------------------------------
/examples/py/binance-fetch-ohlcv.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import asciichart
 6 | 
 7 | # -----------------------------------------------------------------------------
 8 | 
 9 | this_folder = os.path.dirname(os.path.abspath(__file__))
10 | root_folder = os.path.dirname(os.path.dirname(this_folder))
11 | sys.path.append(root_folder + '/python')
12 | sys.path.append(this_folder)
13 | 
14 | # -----------------------------------------------------------------------------
15 | 
16 | import ccxt  # noqa: E402
17 | 
18 | # -----------------------------------------------------------------------------
19 | 
20 | binance = ccxt.binance()
21 | symbol = 'BTC/USDT'
22 | timeframe = '1h'
23 | 
24 | # each ohlcv candle is a list of [ timestamp, open, high, low, close, volume ]
25 | index = 4  # use close price from each ohlcv candle
26 | 
27 | height = 15
28 | length = 80
29 | 
30 | 
31 | def print_chart(exchange, symbol, timeframe):
32 | 
33 |     print("\n" + exchange.name + ' ' + symbol + ' ' + timeframe + ' chart:')
34 | 
35 |     # get a list of ohlcv candles
36 |     ohlcv = exchange.fetch_ohlcv(symbol, timeframe)
37 | 
38 |     # get the ohlCv (closing price, index == 4)
39 |     series = [x[index] for x in ohlcv]
40 | 
41 |     # print the chart
42 |     print("\n" + asciichart.plot(series[-length:], {'height': height}))  # print the chart
43 | 
44 |     last = ohlcv[len(ohlcv) - 1][index]  # last closing price
45 |     return last
46 | 
47 | 
48 | last = print_chart(binance, symbol, timeframe)
49 | print("\n" + binance.name + " ₿ = $" + str(last) + "\n")  # print last closing price
50 | 


--------------------------------------------------------------------------------
/examples/py/binance-test-order.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | 
12 | exchange = ccxt.binance({
13 |     'apiKey': 'YOUR_API_KEY',
14 |     'secret': 'YOUR_SECRET',
15 |     'enableRateLimit': True,
16 | })
17 | 
18 | symbol = 'ETH/BTC'
19 | type = 'limit'  # or 'market'
20 | side = 'sell'  # or 'buy'
21 | amount = 1.0
22 | price = 0.060154  # or None
23 | 
24 | # extra params and overrides if needed
25 | params = {
26 |     'test': True,  # test if it's valid, but don't actually place it
27 | }
28 | 
29 | order = exchange.create_order(symbol, type, side, amount, price, params)
30 | 
31 | print(order)
32 | 


--------------------------------------------------------------------------------
/examples/py/bitfinex-rate-limiting.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | 
12 | symbol = 'ETH/BTC'
13 | 
14 | exchange = ccxt.bitfinex({
15 | 
16 |     'enableRateLimit': True,  # or .enableRateLimit = True later
17 | 
18 |     # BITFINEX RATELIMITS DON'T CORRESPOND TO THEIR DOCUMENTATION!
19 | 
20 |     # their actual rate limit is significantly more strict than documented!
21 |     'rateLimit': 3000,  # once every 3 seconds, 20 times per minute – will work
22 | 
23 |     # this is their documented ratelimit according to this page:
24 |     # https://docs.bitfinex.com/v1/reference#rest-public-orderbook
25 |     # 'rateLimit': 1000,  # once every second, 60 times per minute – won't work, will throw DDoSProtection
26 | })
27 | 
28 | for i in range(0, 100):
29 |     print('--------------------------------------------------------------------')
30 |     print(i)
31 |     print('sent:', exchange.iso8601(exchange.milliseconds()))
32 |     orderbook = exchange.fetch_order_book(symbol)
33 |     print('received:', exchange.iso8601(exchange.milliseconds()), 'bid:', orderbook['bids'][0], 'ask:', orderbook['asks'][0])
34 | 


--------------------------------------------------------------------------------
/examples/py/bitmex-create-order.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | 
12 | exchange = ccxt.bitmex({
13 |     'apiKey': 'YOUR_API_KEY',
14 |     'secret': 'YOUR_SECRET',
15 |     'enableRateLimit': True,
16 | })
17 | 
18 | symbol = 'XBTM18'  # bitcoin contract according to bitmex futures coding
19 | type = 'StopLimit'  # or 'market', or 'Stop' or 'StopLimit'
20 | side = 'sell'  # or 'buy'
21 | amount = 1.0
22 | price = 6500.0  # or None
23 | 
24 | # extra params and overrides
25 | params = {
26 |     'stopPx': 6000.0,  # if needed
27 | }
28 | 
29 | order = exchange.create_order(symbol, type, side, amount, price, params)
30 | print(order)
31 | 


--------------------------------------------------------------------------------
/examples/py/bitmex-fetch-ohlcv-with-extra-params.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import time
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | bitmex = ccxt.bitmex()
13 | 
14 | # params:
15 | symbol = 'BTC/USD'
16 | timeframe = '1m'
17 | limit = 100
18 | params = {'partial': False}  # ←--------  no reversal
19 | 
20 | while True:
21 | 
22 |     # pay attention to since with respect to limit if you're doing it in a loop
23 |     since = bitmex.milliseconds() - limit * 60 * 1000
24 | 
25 |     candles = bitmex.fetch_ohlcv(symbol, timeframe, since, limit, params)
26 |     num_candles = len(candles)
27 |     print('{}: O: {} H: {} L:{} C:{}'.format(
28 |         bitmex.iso8601(candles[num_candles - 1][0]),
29 |         candles[num_candles - 1][1],
30 |         candles[num_candles - 1][2],
31 |         candles[num_candles - 1][3],
32 |         candles[num_candles - 1][4]))
33 |     # * 5 to make distinct delay and to avoid too much load
34 |     # / 1000 to convert milliseconds to fractional seconds
35 |     time.sleep(bitmex.rateLimit * 5 / 1000)
36 | 


--------------------------------------------------------------------------------
/examples/py/bitmex-ohlcv-convert-5m-to-15m.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | from pprint import pprint
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | 
13 | bitmex = ccxt.bitmex({
14 |     'enableRateLimit': True,
15 |     # 'verbose': True,
16 | })
17 | 
18 | # fetch 5m OHLCV
19 | 
20 | symbol = 'BTC/USD'
21 | 
22 | ohlcv5 = bitmex.fetch_ohlcv(symbol, '5m')
23 | ohlcv15 = []
24 | 
25 | # OHLCV key indexes
26 | 
27 | timestamp = 0
28 | open = 1
29 | high = 2
30 | low = 3
31 | close = 4
32 | volume = 5
33 | 
34 | # convert 5m → 15m
35 | 
36 | if len(ohlcv5) > 2:
37 |     for i in range(0, len(ohlcv5) - 2, 3):
38 |         highs = [ohlcv5[i + j][high] for j in range(0, 3) if ohlcv5[i + j][high]]
39 |         lows = [ohlcv5[i + j][low] for j in range(0, 3) if ohlcv5[i + j][low]]
40 |         volumes = [ohlcv5[i + j][volume] for j in range(0, 3) if ohlcv5[i + j][volume]]
41 |         candle = [
42 |             ohlcv5[i + 0][timestamp],
43 |             ohlcv5[i + 0][open],
44 |             max(highs) if len(highs) else None,
45 |             min(lows) if len(lows) else None,
46 |             ohlcv5[i + 2][close],
47 |             sum(volumes) if len(volumes) else None,
48 |         ]
49 |         ohlcv15.append(candle)
50 | else:
51 |     raise Exception('Too few 5m candles')
52 | 
53 | # do whatever you want with your 15m candles here...
54 | 
55 | pprint(ohlcv15)
56 | 


--------------------------------------------------------------------------------
/examples/py/builtin-rate-limiting-long-poller.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | # if you imported the ccxt library with `import ccxt` you can
12 | # set enableRateLimit = True to enable the rate limit in synchronous version of ccxt
13 | # this way you request rate will never hit the limit of an exchange
14 | # the library will throttle your requests to avoid that
15 | 
16 | exchange = ccxt.bitfinex({
17 |     'enableRateLimit': True,  # this option enables the built-in rate limiter
18 | })
19 | 
20 | for i in range(0, 10):
21 |     # this can be any call instead of fetch_ticker, really
22 |     print(exchange.fetch_ticker('BTC/USD'))
23 | 


--------------------------------------------------------------------------------
/examples/py/bypass-cloudflare.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import cfscrape
 4 | import os
 5 | import sys
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | 
13 | def print_supported_exchanges():
14 |     print('Supported exchanges:')
15 |     print(', '.join(ccxt.exchanges))
16 | 
17 | 
18 | try:
19 | 
20 |     id = sys.argv[1]  # get exchange id from command line arguments
21 | 
22 |     # check if the exchange is supported by ccxt
23 |     exchange_found = id in ccxt.exchanges
24 | 
25 |     if exchange_found:
26 | 
27 |         print('Instantiating ' + id + ' exchange')
28 | 
29 |         # instantiate the exchange by id
30 |         exchange = getattr(ccxt, id)({
31 |             'timeout': 20000,
32 |             'session': cfscrape.create_scraper(),
33 |         })
34 | 
35 |         try:
36 | 
37 |             # load all markets from the exchange
38 |             markets = exchange.load_markets()
39 | 
40 |             # output a list of all market symbols
41 |             print(id + ' has ' + str(len(exchange.symbols)) + ' symbols: ' + ', '.join(exchange.symbols))
42 |             print('Succeeded.')
43 | 
44 |         except ccxt.BaseError as e:
45 | 
46 |             print(type(e).__name__, str(e))
47 |             print('Failed.')
48 | 
49 |     else:
50 | 
51 |         print('Exchange ' + id + ' not found')
52 |         print_supported_exchanges()
53 | 
54 | except Exception as e:
55 |     print('[' + type(e).__name__ + ']', str(e))
56 |     print('Usage: python ' + sys.argv[0] + ' id')
57 |     print_supported_exchanges()
58 | 


--------------------------------------------------------------------------------
/examples/py/cryptopia-fetch-order-books.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | from pprint import pprint
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | id = 'cryptopia'
13 | 
14 | # instantiate the exchange by id
15 | exchange = getattr(ccxt, id)({
16 |     # 'proxy':'https://cors-anywhere.herokuapp.com/',
17 | })
18 | 
19 | # load all markets from the exchange
20 | markets = exchange.load_markets()
21 | 
22 | # this will work (a limited number of symbols)
23 | result = exchange.fetch_order_books(['ETH/BTC', 'LTC/BTC'])
24 | pprint(result)
25 | 
26 | # this will also work (a limited number of symbols)
27 | result = exchange.fetch_order_books(exchange.symbols[0:10])
28 | pprint(result)
29 | 
30 | # this will not work (too many symbols)
31 | result = exchange.fetch_order_books(exchange.symbols)
32 | pprint(result)
33 | 


--------------------------------------------------------------------------------
/examples/py/exchanges.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 6 | sys.path.append(root + '/python')
 7 | 
 8 | import ccxt  # noqa: E402
 9 | 
10 | 
11 | def style(s, style):
12 |     return style + s + '\033[0m'
13 | 
14 | 
15 | def green(s):
16 |     return style(s, '\033[92m')
17 | 
18 | 
19 | def blue(s):
20 |     return style(s, '\033[94m')
21 | 
22 | 
23 | def yellow(s):
24 |     return style(s, '\033[93m')
25 | 
26 | 
27 | def red(s):
28 |     return style(s, '\033[91m')
29 | 
30 | 
31 | def pink(s):
32 |     return style(s, '\033[95m')
33 | 
34 | 
35 | def bold(s):
36 |     return style(s, '\033[1m')
37 | 
38 | 
39 | def underline(s):
40 |     return style(s, '\033[4m')
41 | 
42 | 
43 | def log(*args):
44 |     print(' '.join([str(arg) for arg in args]))
45 | 
46 | 
47 | exchanges = {}
48 | 
49 | for id in ccxt.exchanges:
50 |     exchange = getattr(ccxt, id)
51 |     exchanges[id] = exchange()
52 | 
53 | log('The ccxt library supports', green(str(len(ccxt.exchanges))), 'exchanges:')
54 | 
55 | # output a table of all exchanges
56 | log(pink('{:<15} {:<15} {:<15}'.format('id', 'name', 'URL')))
57 | tuples = list(ccxt.Exchange.keysort(exchanges).items())
58 | for (id, params) in tuples:
59 |     exchange = exchanges[id]
60 |     website = exchange.urls['www'][0] if type(exchange.urls['www']) is list else exchange.urls['www']
61 |     log('{:<15} {:<15} {:<15}'.format(exchange.id, exchange.name, website))
62 | 


--------------------------------------------------------------------------------
/examples/py/fetch-gdax-ohlcv-sequentially.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import time
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | # -----------------------------------------------------------------------------
13 | # common constants
14 | 
15 | msec = 1000
16 | minute = 60 * msec
17 | hold = 30
18 | 
19 | # -----------------------------------------------------------------------------
20 | 
21 | exchange = ccxt.gdax({
22 |     'rateLimit': 3000,
23 |     'enableRateLimit': True,
24 |     # 'verbose': True,
25 | })
26 | 
27 | # -----------------------------------------------------------------------------
28 | 
29 | from_datetime = '2017-09-01 00:00:00'
30 | from_timestamp = exchange.parse8601(from_datetime)
31 | 
32 | # -----------------------------------------------------------------------------
33 | 
34 | now = exchange.milliseconds()
35 | 
36 | # -----------------------------------------------------------------------------
37 | 
38 | data = []
39 | 
40 | while from_timestamp < now:
41 | 
42 |     try:
43 | 
44 |         print(exchange.milliseconds(), 'Fetching candles starting from', exchange.iso8601(from_timestamp))
45 |         ohlcvs = exchange.fetch_ohlcv('BTC/USD', '1m', from_timestamp)
46 |         print(exchange.milliseconds(), 'Fetched', len(ohlcvs), 'candles')
47 |         from_timestamp = ohlcvs[-1][0]
48 |         data += ohlcvs
49 | 
50 |     except (ccxt.ExchangeError, ccxt.AuthenticationError, ccxt.ExchangeNotAvailable, ccxt.RequestTimeout) as error:
51 | 
52 |         print('Got an error', type(error).__name__, error.args, ', retrying in', hold, 'seconds...')
53 |         time.sleep(hold)
54 | 


--------------------------------------------------------------------------------
/examples/py/fetch-ohlcv-cex.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import asciichart
 6 | 
 7 | # -----------------------------------------------------------------------------
 8 | 
 9 | this_folder = os.path.dirname(os.path.abspath(__file__))
10 | root_folder = os.path.dirname(os.path.dirname(this_folder))
11 | sys.path.append(root_folder + '/python')
12 | sys.path.append(this_folder)
13 | 
14 | # -----------------------------------------------------------------------------
15 | 
16 | import ccxt  # noqa: E402
17 | 
18 | # -----------------------------------------------------------------------------
19 | 
20 | exchange = ccxt.cex()
21 | symbol = 'BTC/USD'
22 | 
23 | # each ohlcv candle is a list of [ timestamp, open, high, low, close, volume ]
24 | index = 4  # use close price from each ohlcv candle
25 | 
26 | length = 80
27 | height = 15
28 | 
29 | 
30 | def print_chart(exchange, symbol, timeframe):
31 | 
32 |     print("\n" + exchange.name + ' ' + symbol + ' ' + timeframe + ' chart:')
33 | 
34 |     # get a list of ohlcv candles
35 |     ohlcv = exchange.fetch_ohlcv(symbol, timeframe)
36 | 
37 |     # get the ohlCv (closing price, index == 4)
38 |     series = [x[index] for x in ohlcv]
39 | 
40 |     # print the chart
41 |     print("\n" + asciichart.plot(series[-length:], {'height': height}))  # print the chart
42 | 
43 |     last = ohlcv[len(ohlcv) - 1][index]  # last closing price
44 |     return last
45 | 
46 | 
47 | last = print_chart(exchange, symbol, '1m')
48 | print("\n" + exchange.name + " ₿ = $" + str(last) + "\n")  # print last closing price
49 | 


--------------------------------------------------------------------------------
/examples/py/fetch-ohlcv-kraken.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import asciichart
 6 | 
 7 | # -----------------------------------------------------------------------------
 8 | 
 9 | this_folder = os.path.dirname(os.path.abspath(__file__))
10 | root_folder = os.path.dirname(os.path.dirname(this_folder))
11 | sys.path.append(root_folder + '/python')
12 | sys.path.append(this_folder)
13 | 
14 | # -----------------------------------------------------------------------------
15 | 
16 | import ccxt  # noqa: E402
17 | 
18 | # -----------------------------------------------------------------------------
19 | 
20 | exchange = ccxt.kraken()
21 | symbol = 'LTC/EUR'
22 | 
23 | # each ohlcv candle is a list of [ timestamp, open, high, low, close, volume ]
24 | index = 4  # use close price from each ohlcv candle
25 | 
26 | length = 80
27 | height = 15
28 | 
29 | 
30 | def print_chart(exchange, symbol, timeframe):
31 | 
32 |     # get a list of ohlcv candles
33 |     ohlcv = exchange.fetch_ohlcv(symbol, timeframe)
34 | 
35 |     # get the ohlCv (closing price, index == 4)
36 |     series = [x[index] for x in ohlcv]
37 | 
38 |     # print datetime and other values
39 |     for x in ohlcv:
40 |         print(exchange.iso8601(x[0]), x)
41 | 
42 |     print("\n" + exchange.name + ' ' + symbol + ' ' + timeframe + ' chart:')
43 | 
44 |     # print the chart
45 |     print("\n" + asciichart.plot(series[-length:], {'height': height}))  # print the chart
46 | 
47 |     last = ohlcv[len(ohlcv) - 1][index]  # last closing price
48 |     return last
49 | 
50 | 
51 | last = print_chart(exchange, symbol, '1m')
52 | print("\n" + exchange.name + ' last price: ' + str(last) + "\n")  # print last closing price
53 | 


--------------------------------------------------------------------------------
/examples/py/fetch-okex-futures.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import time
 6 | 
 7 | # ------------------------------------------------------------------------------
 8 | 
 9 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10 | sys.path.append(root + '/python')
11 | 
12 | # ------------------------------------------------------------------------------
13 | 
14 | import ccxt  # noqa: E402
15 | 
16 | # ------------------------------------------------------------------------------
17 | 
18 | exchange = ccxt.okex()
19 | exchange.load_markets()
20 | for symbol in exchange.markets:
21 |     market = exchange.markets[symbol]
22 |     if market['future']:
23 |         print('----------------------------------------------------')
24 |         print(symbol, exchange.fetchTicker(symbol))
25 |         time.sleep(exchange.rateLimit / 1000)
26 | 


--------------------------------------------------------------------------------
/examples/py/fetch-orders.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | exchange = ccxt.bittrex({
12 |     "apiKey": "471b47a06c384e81b24072e9a8739064",
13 |     "secret": "694025686e9445589787e8ca212b4cff",
14 |     "enableRateLimit": True,
15 | })
16 | 
17 | orders = exchange.fetch_orders()
18 | print(orders)
19 | 
20 | order = exchange.fetch_order(orders[0]['id'])
21 | print(order)
22 | 


--------------------------------------------------------------------------------
/examples/py/gdax-fetch-my-trades-pagination.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 6 | sys.path.append(root + '/python')
 7 | 
 8 | import ccxt  # noqa: E402
 9 | 
10 | '''
11 | Example snippet to traverse GDAX / CoinBase Pro pagination.
12 | Useful for reaching back more than 100 myTrades, the same works
13 | for fetchClosedOrders
14 | '''
15 | 
16 | exchange = ccxt.gdax({
17 |     "apiKey": "123456",
18 |     "secret": "/abcdefghijklmnop/w==",
19 |     "password": "987654321",
20 |     "enableRateLimit": True
21 | })
22 | 
23 | param_key = ''
24 | param_value = ''
25 | allMyTrades = []
26 | 
27 | while True:
28 |     myTrades = exchange.fetch_my_trades(symbol='BTC/USD', params={param_key: param_value})
29 | 
30 |     # Handle gdax with pagination ...
31 |     if exchange.last_response_headers._store.get('cb-after'):
32 |         param_key = 'after'
33 |         param_value = exchange.last_response_headers._store['cb-after'][1]
34 | 
35 |         allMyTrades.extend(myTrades)
36 | 
37 |     else:
38 |         allMyTrades.extend(myTrades)
39 |         break
40 | 
41 | for trade in allMyTrades:
42 |     print(trade)
43 | 


--------------------------------------------------------------------------------
/examples/py/hitbtc2-withdraw.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | from pprint import pprint
 4 | 
 5 | import os
 6 | import sys
 7 | 
 8 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 9 | sys.path.append(root + '/python')
10 | 
11 | import ccxt  # noqa: E402
12 | 
13 | 
14 | def get_positive_accounts(balance):
15 |     result = {}
16 |     currencies = list(balance.keys())
17 |     for currency in currencies:
18 |         if balance[currency] and balance[currency] > 0:
19 |             result[currency] = balance[currency]
20 |     return result
21 | 
22 | 
23 | exchange = ccxt.hitbtc2({
24 |     "apiKey": "a34ca826b430bdfcca969241b0f7bd2d",
25 |     "secret": "7b28d6b17aea18ae39903add0dae048a",
26 |     "enableRateLimit": True,
27 | })
28 | 
29 | 
30 | trading_balance = exchange.fetch_balance()
31 | account_balance = exchange.fetch_balance({'type': 'account'})
32 | 
33 | pprint('Trading balance:')
34 | pprint(get_positive_accounts(trading_balance['total']))
35 | pprint('Account balance:')
36 | pprint(get_positive_accounts(account_balance['total']))
37 | 
38 | 
39 | withdraw = exchange.withdraw('ETH', 0.01, '0x811DCfeb6dC0b9ed825808B6B060Ca469b83fB81')
40 | 
41 | 
42 | pprint('Withdraw:')
43 | pprint(withdraw)
44 | 


--------------------------------------------------------------------------------
/examples/py/instantiate-all-at-once.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | exchanges = {}  # a placeholder for your instances
12 | 
13 | for id in ccxt.exchanges:
14 |     exchange = getattr(ccxt, id)
15 |     exchanges[id] = exchange()
16 | 
17 | # now exchanges dictionary contains all exchange instances...
18 | exchanges['bittrex'].fetch_order_book('ETH/BTC')
19 | 


--------------------------------------------------------------------------------
/examples/py/manual-rate-limiting-long-poller.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | import time
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | # if you imported the ccxt library with `import ccxt` you can
13 | # throttle your requests manually, by using the rateLimit property of an exchange
14 | # to delay each request by waiting for some time to stay below request rate limits
15 | 
16 | exchange = ccxt.bitfinex()
17 | 
18 | # the rateLimit is in milliseconds → divide it by a thousand to get seconds
19 | delay = exchange.rateLimit / 1000
20 | 
21 | for i in range(0, 10):
22 |     # this can be any call instead of fetch_ticker, really
23 |     print(exchange.fetch_ticker('BTC/USD'))
24 |     time.sleep(delay)  # sleep a little before sending each next request
25 | 


--------------------------------------------------------------------------------
/examples/py/margin-leverage-order-kraken.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | 
12 | kraken = ccxt.kraken({
13 |     'apiKey': 'YOUR_API_KEY',
14 |     'secret': 'YOUR_SECRET',
15 | })
16 | 
17 | kraken.load_markets()
18 | 
19 | for symbol in kraken.symbols:
20 |     print(
21 |         symbol,
22 |         'Available leverage levels',
23 |         'Buy:', kraken.markets[symbol]['info']['leverage_buy'],
24 |         'Sell:', kraken.markets[symbol]['info']['leverage_sell']
25 |     )
26 | 
27 | # THIS IS A KRAKEN-SPECIFIC EXAMPLE.
28 | # THE LEVERAGE WILL NOT WORK WITH OTHER EXCHANGES THE SAME WAY.
29 | # USE IMPLICIT METHODS FOR MARGIN/LEVERAGED ORDERS WITH OTHER EXCHANGES:
30 | # https://github.com/ccxt/ccxt/wiki/Manual#implicit-api-methods
31 | 
32 | # with create_order all params (including the price=None) are needed!
33 | # the extra param should be "leverage", not "leverage_sell" nor "leverage-sell"
34 | kraken.create_order('BTC/USD', 'market', 'sell', 0.01, None, {'leverage': 3})
35 | 
36 | # or use a shorthand create_market_sell_order (no "price" param)
37 | kraken.create_market_sell_order('BTC/USD', 0.01, {'leverage': 3})
38 | 


--------------------------------------------------------------------------------
/examples/py/minimal-2-lines.py:
--------------------------------------------------------------------------------
1 | import ccxt
2 | print(ccxt.bitfinex().fetch_ticker('BTC/USD'))
3 | 


--------------------------------------------------------------------------------
/examples/py/normalize-sparse-candle-timestamps.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | from pprint import pprint
 6 | 
 7 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 8 | sys.path.append(root + '/python')
 9 | 
10 | import ccxt  # noqa: E402
11 | 
12 | exchange = ccxt.cryptopia({'enableRateLimit': True})
13 | 
14 | symbol = 'ETH/BTC'
15 | timeframe = '1h'
16 | 
17 | candles = exchange.fetch_ohlcv(symbol, timeframe)
18 | 
19 | # timeframe duration in seconds
20 | duration = exchange.parse_timeframe(timeframe)
21 | 
22 | # timeframe duration in milliseconds
23 | duration *= 1000
24 | 
25 | pprint([[
26 |     exchange.iso8601(int(round(candle[0] / duration)) * duration),
27 |     candle[1],  # o
28 |     candle[2],  # h
29 |     candle[3],  # l
30 |     candle[4],  # c
31 |     candle[5]   # v
32 | ] for candle in candles])
33 | 


--------------------------------------------------------------------------------
/examples/py/order-book-extra-level-depth-param.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 7 | sys.path.append(root + '/python')
 8 | 
 9 | import ccxt  # noqa: E402
10 | 
11 | # return up to ten bidasks on each side of the order book stack
12 | limit = 10
13 | print(ccxt.cex().fetch_order_book('BTC/USD', limit))
14 | 


--------------------------------------------------------------------------------
/examples/py/proxy-sync-python-requests-2-and-3.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import sys
 5 | 
 6 | from pprint import pprint
 7 | 
 8 | root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 9 | sys.path.append(root + '/python')
10 | 
11 | import ccxt  # noqa: E402
12 | 
13 | exchange = ccxt.poloniex({
14 |     #
15 |     # ↓ The "proxy" property setting below is for CORS-proxying only!
16 |     # Do not use it if you don't know what a CORS proxy is.
17 |     # https://github.com/ccxt/ccxt/wiki/Install#cors-access-control-allow-origin
18 |     # You should only use the "proxy" setting if you're having a problem with Access-Control-Allow-Origin
19 |     # In Python you rarely need to use it, if ever at all.
20 |     #
21 |     # 'proxy': 'https://cors-anywhere.herokuapp.com/',
22 |     #
23 |     # ↓ On the other hand, the "proxies" setting is for HTTP(S)-proxying (SOCKS, etc...)
24 |     # It is a standard method of sending your requests through your proxies
25 |     # This gets passed to the `python-requests` implementation directly
26 |     # You can also enable this with environment variables, as described here:
27 |     # http://docs.python-requests.org/en/master/user/advanced/#proxies
28 |     # The environment variables should be set before importing ccxt (!)
29 |     # This is the setting you should be using with synchronous version of ccxt in Python 2 and 3
30 |     #
31 |     'proxies': {
32 |         'http': 'http://10.10.1.10:3128',
33 |         'https': 'http://10.10.1.10:1080',
34 |     },
35 | })
36 | 
37 | # your code goes here...
38 | 
39 | pprint(exchange.fetch_ticker('ETH/BTC'))
40 | 


--------------------------------------------------------------------------------
/exchanges.cfg:
--------------------------------------------------------------------------------
 1 | # -------------------------------------------------------------------------------
 2 | # You can create a custom bundle of CCXT including only the exchanges you need.
 3 | # Add or uncomment ids below and launch `npm run build`.
 4 | # Leaving this config empty will build all exchanges.
 5 | # -------------------------------------------------------------------------------
 6 | 
 7 | # binance
 8 | # huobi
 9 | # kraken
10 | 


--------------------------------------------------------------------------------
/js/base/.eslintrc.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | module.exports = {
 4 |   "env": {
 5 |     "node": true,
 6 |     "es6": true,
 7 |     "browser": true,
 8 |   },
 9 |   "parserOptions": {
10 |     "ecmaVersion": 2017,
11 |     "sourceType": "script",
12 |   },
13 |   "rules": {
14 |       "semi": "off",
15 |       "no-unused-vars": ["off"],
16 |       "quotes": ["off", "single"],
17 |       "quote-props": "off",
18 |       "func-call-spacing": ["error", "always"],
19 |       "one-var": "off",
20 |       "indent": ["warn", 4, { "ignoredNodes": ["ObjectPattern"] }],
21 |       "comma-style": "off",
22 |       "no-multi-spaces": "off",
23 |       "comma-dangle": "off",
24 |       "spaced-comment": "off",
25 |       "camelcase": "off",
26 |       "padded-blocks": "off",
27 |       "multiline-comment-style": "off",
28 |       "curly": "off",
29 |       "rest-spread-spacing": "off",
30 |       "no-multiple-empty-lines": "off",
31 |       "no-undef-init": "off",
32 |       "no-useless-return": "off",
33 |       "no-console": "off",
34 |       "operator-linebreak": "off",
35 |       "key-spacing": "off",
36 |       "brace-style": "off",
37 |       "padding-line-between-statements": ["off",
38 |         {"blankLine": "never", "prev":"*", "next": "*" },
39 |         {"blankLine": "always", "prev":"directive", "next": "*" },
40 |         {"blankLine": "always", "prev":"*", "next": "cjs-export" },
41 |       ],
42 |   },
43 | }
44 | 


--------------------------------------------------------------------------------
/js/base/Market.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | module.exports = class Market {
 4 | 
 5 |     constructor (exchange, symbol) {
 6 |         this.exchange = exchange;
 7 |         this.symbol = symbol;
 8 |         this.market = exchange.markets[symbol];
 9 |     }
10 | 
11 |     amountToPrecision (amount) {
12 |         return this.exchange.amountToPrecision (this.symbol, amount)
13 |     }
14 | 
15 |     createLimitBuyOrder(amount, price) {
16 |         return this.exchange.createLimitBuyOrder (this.symbol, amount, price)
17 |     }
18 | 
19 |     createLimitSellOrder(amount, price) {
20 |         return this.exchange.createLimitSellOrder (this.symbol, amount, price)
21 |     }
22 | }
23 | 


--------------------------------------------------------------------------------
/js/base/functions.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | /*  ------------------------------------------------------------------------ */
 4 | 
 5 | const { unCamelCase } = require ('./functions/string')
 6 | 
 7 | const unCamelCasePropertyNames = x => {
 8 |     for (const k in x) x[unCamelCase (k)] = x[k] // camel_case_method = camelCaseMethod
 9 |     return x
10 | }
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = unCamelCasePropertyNames (Object.assign ({}
15 | 
16 |     , require ('./functions/platform')
17 |     , require ('./functions/generic')
18 |     , require ('./functions/string')
19 |     , require ('./functions/type')
20 |     , require ('./functions/number')
21 |     , require ('./functions/encode')
22 |     , require ('./functions/crypto')
23 |     , require ('./functions/time')
24 |     , require ('./functions/throttle')
25 |     , require ('./functions/misc')
26 | ))
27 | 
28 | /*  ------------------------------------------------------------------------ */
29 | 


--------------------------------------------------------------------------------
/js/base/functions/platform.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | // There's been a lot of messing with this code...
 5 | // The problem is to satisfy the following requirements:
 6 | // - properly detect isNode == true on server side and isNode == false in the browser (on client side)
 7 | // - make sure create-react-app, react-starter-kit and other react frameworks work
 8 | // - make sure it does not break the browserified version (when linked into a html from a cdn)
 9 | // - make sure it does not break the webpacking and babel-transpiled scripts
10 | // - make sure it works in Electron
11 | // - make sure it works with Angular.js
12 | // - make sure it does not break other possible usage scenarios
13 | 
14 | const isBrowser = typeof window !== 'undefined'
15 | 
16 | const isElectron = typeof process !== 'undefined' &&
17 |                    typeof process.versions !== 'undefined' &&
18 |                    typeof process.versions.electron !== 'undefined'
19 | 
20 | const isWebWorker = typeof WorkerGlobalScope !== 'undefined' && (self instanceof WorkerGlobalScope)
21 | 
22 | const isWindows = typeof process !== 'undefined' && process.platform === "win32"
23 | 
24 | const isNode = !(isBrowser || isWebWorker)
25 | 
26 | // ----------------------------------------------------------------------------
27 | 
28 | module.exports = {
29 | 
30 |     isBrowser,
31 |     isElectron,
32 |     isWebWorker,
33 |     isNode,
34 |     isWindows,
35 | }


--------------------------------------------------------------------------------
/js/base/functions/string.js:
--------------------------------------------------------------------------------
 1 | "use strict";
 2 | 
 3 | /*  ------------------------------------------------------------------------ */
 4 | 
 5 | const uuid = a => a ? (a ^ Math.random () * 16 >> a / 4).toString (16)
 6 |                     : ([1e7]+-1e3+-4e3+-8e3+-1e11).replace (/[018]/g, uuid)
 7 | 
 8 | module.exports =
 9 | 
10 |     { uuid
11 | 
12 |       // hasFetchOHLCV → has_fetch_ohlcv; parseHTTPResponse → parse_http_response
13 |     , unCamelCase: s => s.match (/^[A-Z0-9_]+$/) ? s : (s.replace (/[a-z0-9][A-Z]/g, x => x[0] + '_' + x[1]).replace(/[A-Z0-9][A-Z0-9][a-z]/g, x => x[0] + '_' + x[1] + x[2]).toLowerCase ())
14 | 
15 |     , capitalize: s => s.length
16 |                             ? (s.charAt (0).toUpperCase () + s.slice (1))
17 |                             : s
18 |     }
19 | 
20 | /*  ------------------------------------------------------------------------ */
21 | 


--------------------------------------------------------------------------------
/js/bitkk.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | //  ---------------------------------------------------------------------------
 4 | 
 5 | const zb = require ('./zb.js');
 6 | 
 7 | //  ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class bitkk extends zb {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'bitkk',
13 |             'name': 'bitkk',
14 |             'comment': 'a Chinese ZB clone',
15 |             'urls': {
16 |                 'api': {
17 |                     'public': 'http://api.bitkk.com/data', // no https for public API
18 |                     'private': 'https://trade.bitkk.com/api',
19 |                 },
20 |                 'www': 'https://www.bitkk.com',
21 |                 'doc': 'https://www.bitkk.com/i/developer',
22 |                 'fees': 'https://www.bitkk.com/i/rate',
23 |             },
24 |         });
25 |     }
26 | };
27 | 


--------------------------------------------------------------------------------
/js/btcexchange.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const btcturk = require ('./btcturk.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class btcexchange extends btcturk {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'btcexchange',
13 |             'name': 'BTCExchange',
14 |             'countries': [ 'PH' ], // Philippines
15 |             'rateLimit': 1500,
16 |             'has': {
17 |                 'CORS': false,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27993052-4c92911a-64aa-11e7-96d8-ec6ac3435757.jpg',
21 |                 'api': 'https://www.btcexchange.ph/api',
22 |                 'www': 'https://www.btcexchange.ph',
23 |                 'doc': 'https://github.com/BTCTrader/broker-api-docs',
24 |             },
25 |             'markets': {
26 |                 'BTC/PHP': { 'id': 'BTC/PHP', 'symbol': 'BTC/PHP', 'base': 'BTC', 'quote': 'PHP' },
27 |             },
28 |         });
29 |     }
30 | };
31 | 


--------------------------------------------------------------------------------
/js/chilebit.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const foxbit = require ('./foxbit.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class chilebit extends foxbit {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'chilebit',
13 |             'name': 'ChileBit',
14 |             'countries': [ 'CL' ],
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg',
20 |                 'api': {
21 |                     'public': 'https://api.blinktrade.com/api',
22 |                     'private': 'https://api.blinktrade.com/tapi',
23 |                 },
24 |                 'www': 'https://chilebit.net',
25 |                 'doc': 'https://blinktrade.com/docs',
26 |             },
27 |             'options': {
28 |                 'brokerId': '9', // https://blinktrade.com/docs/#brokers
29 |             },
30 |         });
31 |     }
32 | };
33 | 


--------------------------------------------------------------------------------
/js/coinbaseprime.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const gdax = require ('./gdax.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class coinbaseprime extends gdax {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'coinbaseprime',
13 |             'name': 'Coinbase Prime',
14 |             'urls': {
15 |                 'test': 'https://api-public.sandbox.prime.coinbase.com',
16 |                 'logo': 'https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg',
17 |                 'api': 'https://api.prime.coinbase.com',
18 |                 'www': 'https://prime.coinbase.com',
19 |                 'doc': 'https://docs.prime.coinbase.com',
20 |                 'fees': 'https://support.prime.coinbase.com/customer/en/portal/articles/2945629-fees?b_id=17475',
21 |             },
22 |         });
23 |     }
24 | };
25 | 


--------------------------------------------------------------------------------
/js/coinbasepro.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const gdax = require ('./gdax.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class coinbasepro extends gdax {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'coinbasepro',
13 |             'name': 'Coinbase Pro',
14 |             'urls': {
15 |                 'test': 'https://api-public.sandbox.pro.coinbase.com',
16 |                 'logo': 'https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg',
17 |                 'api': 'https://api.pro.coinbase.com',
18 |                 'www': 'https://pro.coinbase.com/',
19 |                 'doc': 'https://docs.pro.coinbase.com/',
20 |                 'fees': [
21 |                     'https://docs.pro.coinbase.com/#fees',
22 |                     'https://support.pro.coinbase.com/customer/en/portal/articles/2945310-fees',
23 |                 ],
24 |             },
25 |         });
26 |     }
27 | };
28 | 


--------------------------------------------------------------------------------
/js/fybsg.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const fybse = require ('./fybse.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class fybsg extends fybse {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'fybsg',
13 |             'name': 'FYB-SG',
14 |             'countries': [ 'SG' ], // Singapore
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766513-3364d56a-5edb-11e7-9e6b-d5898bb89c81.jpg',
20 |                 'api': 'https://www.fybsg.com/api/SGD',
21 |                 'www': 'https://www.fybsg.com',
22 |                 'doc': 'http://docs.fyb.apiary.io',
23 |             },
24 |             'markets': {
25 |                 'BTC/SGD': { 'id': 'SGD', 'symbol': 'BTC/SGD', 'base': 'BTC', 'quote': 'SGD' },
26 |             },
27 |         });
28 |     }
29 | };
30 | 


--------------------------------------------------------------------------------
/js/huobicny.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const huobipro = require ('./huobipro.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class huobicny extends huobipro {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'huobicny',
13 |             'name': 'Huobi CNY',
14 |             'hostname': 'be.huobi.com',
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766569-15aa7b9a-5edd-11e7-9e7f-44791f4ee49c.jpg',
20 |                 'api': {
21 |                     'public': 'https://be.huobi.com',
22 |                     'private': 'https://be.huobi.com',
23 |                     'market': 'https://be.huobi.com',
24 |                 },
25 |                 'www': 'https://www.huobi.com',
26 |                 'doc': 'https://github.com/huobiapi/API_Docs/wiki/REST_api_reference',
27 |             },
28 |         });
29 |     }
30 | };
31 | 


--------------------------------------------------------------------------------
/js/qryptos.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const liquid = require ('./liquid');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class qryptos extends liquid {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'qryptos',
13 |             'name': 'QRYPTOS',
14 |         });
15 |     }
16 | };
17 | 


--------------------------------------------------------------------------------
/js/quoinex.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const liquid = require ('./liquid');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class quoinex extends liquid {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'quoinex',
13 |             'name': 'QUOINEX',
14 |         });
15 |     }
16 | };
17 | 


--------------------------------------------------------------------------------
/js/surbitcoin.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const foxbit = require ('./foxbit.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class surbitcoin extends foxbit {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'surbitcoin',
13 |             'name': 'SurBitcoin',
14 |             'countries': [ 'VE' ],
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991511-f0a50194-6481-11e7-99b5-8f02932424cc.jpg',
20 |                 'api': {
21 |                     'public': 'https://api.blinktrade.com/api',
22 |                     'private': 'https://api.blinktrade.com/tapi',
23 |                 },
24 |                 'www': 'https://surbitcoin.com',
25 |                 'doc': 'https://blinktrade.com/docs',
26 |             },
27 |             'options': {
28 |                 'brokerId': '1', // https://blinktrade.com/docs/#brokers
29 |             },
30 |         });
31 |     }
32 | };
33 | 


--------------------------------------------------------------------------------
/js/test/.eslintrc.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | module.exports = {
 4 |   "env": {
 5 |     "node": true,
 6 |     "mocha": true
 7 |   },
 8 |   "parserOptions": {
 9 |     "ecmaVersion": 2017,
10 |     "sourceType": "script",
11 |   },
12 |   "extends": ["eslint:recommended"],
13 |   "rules": {
14 |       "semi": ["error", "never"],
15 |       "no-unused-vars": ["off"],
16 |       "quotes": ["off", "single"],
17 |       "func-call-spacing": ["error", "always"],
18 |       "one-var": "off",
19 |       "indent": ["error", 4],
20 |       "comma-style": "off",
21 |       "no-multi-spaces": "off",
22 |       "comma-dangle": "off",
23 |       "spaced-comment": "off",
24 |       "camelcase": "off",
25 |       "padded-blocks": "off",
26 |       "multiline-comment-style": "off",
27 |       "curly": "off",
28 |       "rest-spread-spacing": "off",
29 |       "no-multiple-empty-lines": "off",
30 |       "no-undef-init": "off",
31 |       "no-useless-return": "off",
32 |       "no-console": "off",
33 |       "operator-linebreak": "off",
34 |       "key-spacing": "off",
35 |       "brace-style": "off",
36 |       "padding-line-between-statements": ["off",
37 |         { "blankLine": "always", "prev":"function", "next": "*" },
38 |         { "blankLine": "always", "prev":"directive", "next": "*" },
39 |         { "blankLine": "always", "prev":"*", "next": "cjs-export" },
40 |       ],
41 |       "import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
42 |     },
43 | }
44 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchClosedOrders.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrder = require ('./test.order.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (exchange.has.fetchClosedOrders) {
17 | 
18 |         // log ('fetching closed orders...')
19 | 
20 |         let orders = await exchange.fetchClosedOrders (symbol)
21 | 
22 |         log ('fetched', orders.length.toString ().green, 'closed orders, testing each')
23 | 
24 |         assert (orders instanceof Array)
25 | 
26 |         let now = Date.now ()
27 | 
28 |         for (let i = 0; i < orders.length; i++) {
29 |             let order = orders[i]
30 |             testOrder (exchange, order, symbol, now)
31 |             assert (order.status === 'closed')
32 |         }
33 | 
34 |         // log (asTable (orders))
35 | 
36 |     } else {
37 | 
38 |         log ('fetching closed orders not supported')
39 |     }
40 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchCurrencies.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testCurrency = require ('./test.currency.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange) => {
15 | 
16 |     const skippedExchanges = [
17 |     ]
18 | 
19 |     if (skippedExchanges.includes (exchange.id)) {
20 |         log (exchange.id, 'found in ignored exchanges, skipping fetchCurrencies...')
21 |         return
22 |     }
23 | 
24 |     if (exchange.has.fetchCurrencies) {
25 | 
26 |         // log ('fetching currencies...')
27 | 
28 |         const method = 'fetchCurrencies'
29 |         const currencies = await exchange[method] ()
30 |         Object.values (currencies).forEach (currency => testCurrency (exchange, currency, method))
31 |         return currencies
32 | 
33 |     } else {
34 | 
35 |         log ('fetching currencies not supported')
36 |     }
37 | }
38 | 
39 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchFundingFees.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 | 
11 | /*  ------------------------------------------------------------------------ */
12 | 
13 | module.exports = async (exchange) => {
14 | 
15 |     const skippedExchanges = [
16 |     ]
17 | 
18 |     if (skippedExchanges.includes (exchange.id)) {
19 |         log (exchange.id, 'found in ignored exchanges, skipping fetchFundingFees...')
20 |         return
21 |     }
22 | 
23 |     if (exchange.has.fetchFundingFees) {
24 | 
25 |         // log ('fetching funding fees...')
26 | 
27 |         const method = 'fetchFundingFees'
28 |         const fees = await exchange[method] ()
29 |         log.green (fees)
30 |         return fees
31 | 
32 |     } else {
33 | 
34 |         log ('fetching funding fees not supported')
35 |     }
36 | }
37 | 
38 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchL2OrderBook.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrderBook = require ('./test.orderbook.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     // log (symbol.green, 'fetching order book...')
17 | 
18 |     const method = 'fetchL2OrderBook'
19 | 
20 |     if (exchange.has[method]) {
21 | 
22 |         let orderbook = await exchange[method] (symbol)
23 |         testOrderBook (exchange, orderbook, method, symbol)
24 |         return orderbook
25 | 
26 |     } else {
27 | 
28 |         log (method + '() not supported')
29 |     }
30 | 
31 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchMarkets.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testMarket = require ('./test.market.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange) => {
15 | 
16 |     const skippedExchanges = [
17 |         'bitforex',
18 |     ]
19 | 
20 |     if (skippedExchanges.includes (exchange.id)) {
21 |         log (exchange.id, 'found in ignored exchanges, skipping fetchMarkets...')
22 |         return
23 |     }
24 | 
25 |     if (exchange.has.fetchMarkets) {
26 | 
27 |         // log ('fetching markets...')
28 | 
29 |         const method = 'fetchMarkets'
30 |         const markets = await exchange[method] ()
31 |         Object.values (markets).forEach (market => testMarket (exchange, market, method))
32 |         return markets
33 | 
34 |     } else {
35 | 
36 |         log ('fetching markets not supported')
37 |     }
38 | }
39 | 
40 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchMyTrades.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testTrade = require ('./test.trade.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (exchange.has.fetchMyTrades) {
17 | 
18 |         // log ('fetching my trades...')
19 | 
20 |         let trades = await exchange.fetchMyTrades (symbol, 0)
21 | 
22 |         assert (trades instanceof Array)
23 | 
24 |         log ('fetched', trades.length.toString ().green, 'trades')
25 | 
26 |         let now = Date.now ()
27 | 
28 |         for (let i = 0; i < trades.length; i++) {
29 |             testTrade (exchange, trades[i], symbol, now)
30 |             if (i > 0)
31 |                 assert (trades[i].timestamp >= trades[i - 1].timestamp)
32 |         }
33 | 
34 |         // trades.forEach (trade => log.dim ('-'.repeat (80), "\n", trade))
35 |         // log (asTable (trades))
36 | 
37 |     } else {
38 | 
39 |         log ('fetching my trades not supported')
40 |     }
41 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchOHLCV.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 | 
11 | /*  ------------------------------------------------------------------------ */
12 | 
13 | module.exports = async (exchange, symbol) => {
14 | 
15 |     if (exchange.has.fetchOHLCV) {
16 | 
17 |         // log (symbol.green, 'fetching OHLCV...')
18 | 
19 |         let ohlcv = await exchange.fetchOHLCV (symbol)
20 | 
21 |         log (symbol.green, 'fetched', Object.keys (ohlcv).length.toString ().green, 'OHLCVs')
22 | 
23 |         return ohlcv
24 | 
25 |     } else {
26 | 
27 |         log ('fetching OHLCV not supported')
28 |     }
29 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchOpenOrders.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrder = require ('./test.order.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (exchange.has.fetchOpenOrders) {
17 | 
18 |         // log ('fetching open orders...')
19 | 
20 |         let orders = await exchange.fetchOpenOrders (symbol)
21 | 
22 |         assert (orders instanceof Array)
23 | 
24 |         log ('fetched', orders.length.toString ().green, 'open orders')
25 | 
26 |         let now = Date.now ()
27 | 
28 |         for (let i = 0; i < orders.length; i++) {
29 |             let order = orders[i]
30 |             testOrder (exchange, order, symbol, now)
31 |             assert (order.status === 'open')
32 |         }
33 | 
34 |         // log (asTable (orders))
35 | 
36 |     } else {
37 | 
38 |         log ('fetching open orders not supported')
39 |     }
40 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchOrderBook.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrderBook = require ('./test.orderbook.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     // log (symbol.green, 'fetching order book...')
17 | 
18 |     const method = 'fetchOrderBook'
19 | 
20 |     if (exchange.has[method]) {
21 | 
22 |         let orderbook = await exchange[method] (symbol)
23 | 
24 |         testOrderBook (exchange, orderbook, method, symbol)
25 | 
26 |         return orderbook
27 | 
28 |     } else {
29 | 
30 |         log (method + '() not supported')
31 |     }
32 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchOrderBooks.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrderBook = require ('./test.orderbook.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange) => {
15 | 
16 |     const randomSymbols = exchange.symbols.sort (() => 0.5 - Math.random ()).slice (0, 2)
17 |     const customExchangeParams = ([
18 |         'yobit',
19 |         'tidex',
20 |         'cryptopia',
21 |         'ccex',
22 |         'liqui',
23 |     ]).reduce ((params, id) => ({ ...params, [id]: [randomSymbols], }), {})
24 | 
25 |     const args = (exchange.id in customExchangeParams) ? customExchangeParams[exchange.id] : []
26 |     const method = 'fetchOrderBooks'
27 | 
28 |     if (exchange.has[method]) {
29 | 
30 |         // log ('fetching order books...')
31 | 
32 |         let orderbooks = await exchange[method] (...args)
33 | 
34 |         // log.green (orderbooks)
35 | 
36 |         Object.entries (orderbooks).forEach (([symbol, orderbook]) => {
37 |             testOrderBook (exchange, orderbook, method, symbol)
38 |         })
39 | 
40 |         // return orderbooks
41 | 
42 |     } else {
43 | 
44 |         log (method + '() not supported')
45 |     }
46 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchOrders.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testOrder = require ('./test.order.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (exchange.has.fetchOrders) {
17 | 
18 |         // log ('fetching orders...')
19 | 
20 |         let orders = await exchange.fetchOrders (symbol)
21 | 
22 |         log ('fetched', orders.length.toString ().green, 'orders, asserting each...')
23 | 
24 |         assert (orders instanceof Array)
25 | 
26 |         let now = Date.now ()
27 | 
28 |         for (let i = 0; i < orders.length; i++) {
29 |             let order = orders[i]
30 |             testOrder (exchange, order, symbol, now)
31 |         }
32 | 
33 |         // log (asTable (orders))
34 | 
35 |     } else {
36 | 
37 |         log ('fetching orders not supported')
38 |     }
39 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchTicker.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testTicker = require ('./test.ticker.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     const method = 'fetchTicker'
17 | 
18 |     if (exchange.has[method]) {
19 | 
20 |         // log (symbol.green, 'fetching ticker...')
21 | 
22 |         let ticker = await exchange.fetchTicker (symbol)
23 | 
24 |         testTicker (exchange, ticker, method, symbol)
25 | 
26 |         return ticker
27 | 
28 |     } else {
29 | 
30 |         log (symbol.green, 'fetchTicker () not supported')
31 |     }
32 | }
33 | 
34 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchTickers.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testTicker = require ('./test.ticker.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     const skippedExchanges = [
17 |         'binance',
18 |     ]
19 | 
20 |     if (skippedExchanges.includes (exchange.id)) {
21 |         log (exchange.id, 'found in ignored exchanges, skipping fetch all tickers...')
22 |         return
23 |     }
24 | 
25 |     if (exchange.has.fetchTickers) {
26 | 
27 |         // log ('fetching all tickers at once...')
28 | 
29 |         const method = 'fetchTickers'
30 |         let tickers = undefined
31 | 
32 |         try {
33 | 
34 |             tickers = await exchange[method] ()
35 |             log ('fetched all', Object.keys (tickers).length.toString ().green, 'tickers')
36 | 
37 |         } catch (e) {
38 | 
39 |             log ('failed to fetch all tickers, fetching multiple tickers at once...')
40 |             tickers = await exchange[method] ([ symbol ])
41 |             log ('fetched', Object.keys (tickers).length.toString ().green, 'tickers')
42 |         }
43 | 
44 |         Object.values (tickers).forEach (ticker => testTicker (exchange, ticker, method, symbol))
45 |         return tickers
46 | 
47 |     } else {
48 | 
49 |         log ('fetching all tickers at once not supported')
50 |     }
51 | }
52 | 
53 | 


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchTrades.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 |     , testTrade = require ('./test.trade.js')
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (exchange.has.fetchTrades) {
17 | 
18 |         // log (symbol.green, 'fetching trades...')
19 | 
20 |         let trades = await exchange.fetchTrades (symbol)
21 |         assert (trades instanceof Array)
22 |         log (symbol.green, 'fetched', Object.values (trades).length.toString ().green, 'trades')
23 |         let now = Date.now ()
24 |         for (let i = 0; i < trades.length; i++) {
25 |             testTrade (exchange, trades[i], symbol, now)
26 |             if (i > 0)
27 |                 assert (trades[i].timestamp >= trades[i - 1].timestamp)
28 |         }
29 |         // log (asTable (trades))
30 | 
31 |     } else {
32 | 
33 |         log (symbol.green, 'fetchTrades () not supported'.yellow)
34 |     }
35 | }


--------------------------------------------------------------------------------
/js/test/Exchange/test.fetchTradingFees.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 | 
11 | /*  ------------------------------------------------------------------------ */
12 | 
13 | module.exports = async (exchange) => {
14 | 
15 |     const skippedExchanges = [
16 |     ]
17 | 
18 |     if (skippedExchanges.includes (exchange.id)) {
19 |         log (exchange.id, 'found in ignored exchanges, skipping fetchTradingFees...')
20 |         return
21 |     }
22 | 
23 |     if (exchange.has.fetchTradingFees) {
24 | 
25 |         // log ('fetching trading fees...')
26 | 
27 |         const method = 'fetchTradingFees'
28 |         const fees = await exchange[method] ()
29 |         log.green (fees)
30 |         return fees
31 | 
32 |     } else {
33 | 
34 |         log ('fetching trading fees not supported')
35 |     }
36 | }
37 | 
38 | 


--------------------------------------------------------------------------------
/js/test/Exchange/tmp.test.fetchOHLCV.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , expect    = chai.expect
 9 |     , assert    = chai.assert
10 | 
11 | /*  ------------------------------------------------------------------------ */
12 | 
13 | module.exports = async (exchange, symbol) => {
14 | 
15 |     if (exchange.has.fetchOHLCV) {
16 | 
17 |         // log (symbol.green, 'fetching OHLCV...')
18 | 
19 |         let ohlcvs = await exchange.fetchOHLCV (symbol)
20 | 
21 |         log (symbol.green, 'fetched', Object.keys (ohlcvs).length.toString ().green, 'OHLCVs')
22 | 
23 |         // let now = Date.now ()
24 |         for (let i = 1; i < ohlcvs.length; i++) {
25 |             // testOHLCV (exchange, ohlcvs[i], symbol, now)
26 |             assert (ohlcvs[i][0] >= ohlcvs[i - 1][0], 'OHLCV timestamps out of order: ' + ohlcvs[i][0] + ' < ' + ohlcvs[i - 1][0])
27 |         }
28 | 
29 |         return ohlcvs
30 | 
31 |     } else {
32 | 
33 |         log ('fetching OHLCV not supported')
34 |     }
35 | }


--------------------------------------------------------------------------------
/js/test/base/.eslintrc:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | module.exports = {
 4 |   "env": {
 5 |     "node": true,
 6 |     "mocha": true
 7 |   },
 8 |   "parserOptions": {
 9 |     "ecmaVersion": 2017,
10 |     "sourceType": "script",
11 |   },
12 |   "rules": {
13 |       "semi": ["error", "never"],
14 |       "no-unused-vars": ["off"],
15 |       "quotes": ["off", "single"],
16 |       "func-call-spacing": ["error", "always"],
17 |       "one-var": "off",
18 |       "indent": ["warn", 4, { "ignoredNodes": ["ObjectPattern"] }],
19 |       "comma-style": "off",
20 |       "no-multi-spaces": "off",
21 |       "comma-dangle": "off",
22 |       "spaced-comment": "off",
23 |       "camelcase": "off",
24 |       "padded-blocks": "off",
25 |       "multiline-comment-style": "off",
26 |       "curly": "off",
27 |       "rest-spread-spacing": "off",
28 |       "no-multiple-empty-lines": "off",
29 |       "no-undef-init": "off",
30 |       "no-useless-return": "off",
31 |       "no-console": "off",
32 |       "operator-linebreak": "off",
33 |       "key-spacing": "off",
34 |       "brace-style": "off",
35 |       "padding-line-between-statements": ["off",
36 |         {"blankLine": "always", "prev":"function", "next": "*" },
37 |         {"blankLine": "always", "prev":"directive", "next": "*" },
38 |         {"blankLine": "always", "prev":"*", "next": "cjs-export" },
39 |       ],
40 |   },
41 | }
42 | 


--------------------------------------------------------------------------------
/js/test/errors/test.InvalidOrder.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , ccxt      = require ('../../../ccxt.js')
 9 |     , expect    = chai.expect
10 |     , assert    = chai.assert
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (!exchange.has.createOrder) {
17 |         log ('createOrder not supported')
18 |         return
19 |     }
20 | 
21 |     try {
22 | 
23 |         await exchange.createLimitBuyOrder (symbol, 0, 0)
24 |         assert.fail ()
25 | 
26 |     } catch (e) {
27 | 
28 |         if (e instanceof ccxt.InvalidOrder) {
29 | 
30 |             log ('InvalidOrder thrown as expected')
31 |             return
32 | 
33 |         } else {
34 | 
35 |             log ('InvalidOrder failed, exception follows:')
36 |             throw e
37 |         }
38 |     }
39 | }


--------------------------------------------------------------------------------
/js/test/errors/test.OrderNotFound.js:
--------------------------------------------------------------------------------
 1 | 'use strict'
 2 | 
 3 | // ----------------------------------------------------------------------------
 4 | 
 5 | const log       = require ('ololog')
 6 |     , ansi      = require ('ansicolor').nice
 7 |     , chai      = require ('chai')
 8 |     , ccxt      = require ('../../../ccxt.js')
 9 |     , expect    = chai.expect
10 |     , assert    = chai.assert
11 | 
12 | /*  ------------------------------------------------------------------------ */
13 | 
14 | module.exports = async (exchange, symbol) => {
15 | 
16 |     if (!exchange.has.createOrder) {
17 |         log ('createOrder not supported -> test skipped')
18 |         return
19 |     }
20 | 
21 |     let id = 1
22 | 
23 |     try {
24 | 
25 |         await exchange.cancelOrder (id, symbol)
26 | 
27 |         log ('test failed')
28 | 
29 |         assert.fail ()
30 | 
31 |     } catch (e) {
32 | 
33 |         if (e instanceof ccxt.OrderNotFound) {
34 | 
35 |             log ('OrderNotFound thrown as expected')
36 | 
37 |         } else {
38 | 
39 |             log ('OrderNotFound test failed')
40 |             throw e
41 |         }
42 |     }
43 | }


--------------------------------------------------------------------------------
/js/test/test.timeout_hang.js:
--------------------------------------------------------------------------------
 1 | // run with `node test_timeout_hang`
 2 | // TODO: integrate with CI tests somehow...
 3 | 
 4 | const { timeout } = require ('../base/functions')
 5 | 
 6 | ;(async function () {
 7 | 
 8 |     await timeout (10000, Promise.resolve ('foo'))
 9 | 
10 |     console.log ('Look ma, no hangs!') // should terminate the process immediately..
11 | 
12 | }) ()


--------------------------------------------------------------------------------
/js/urdubit.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const foxbit = require ('./foxbit.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class urdubit extends foxbit {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'urdubit',
13 |             'name': 'UrduBit',
14 |             'countries': [ 'PK' ],
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991453-156bf3ae-6480-11e7-82eb-7295fe1b5bb4.jpg',
20 |                 'api': {
21 |                     'public': 'https://api.blinktrade.com/api',
22 |                     'private': 'https://api.blinktrade.com/tapi',
23 |                 },
24 |                 'www': 'https://urdubit.com',
25 |                 'doc': 'https://blinktrade.com/docs',
26 |             },
27 |             'options': {
28 |                 'brokerId': '8', // https://blinktrade.com/docs/#brokers
29 |             },
30 |         });
31 |     }
32 | };
33 | 


--------------------------------------------------------------------------------
/js/vbtc.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | // ---------------------------------------------------------------------------
 4 | 
 5 | const foxbit = require ('./foxbit.js');
 6 | 
 7 | // ---------------------------------------------------------------------------
 8 | 
 9 | module.exports = class vbtc extends foxbit {
10 |     describe () {
11 |         return this.deepExtend (super.describe (), {
12 |             'id': 'vbtc',
13 |             'name': 'VBTC',
14 |             'countries': [ 'VN' ],
15 |             'has': {
16 |                 'CORS': false,
17 |             },
18 |             'urls': {
19 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg',
20 |                 'api': {
21 |                     'public': 'https://api.blinktrade.com/api',
22 |                     'private': 'https://api.blinktrade.com/tapi',
23 |                 },
24 |                 'www': 'https://vbtc.exchange',
25 |                 'doc': 'https://blinktrade.com/docs',
26 |             },
27 |             'options': {
28 |                 'brokerId': '3', // https://blinktrade.com/docs/#brokers
29 |             },
30 |         });
31 |     }
32 | };
33 | 


--------------------------------------------------------------------------------
/php/AccountSuspended.php:
--------------------------------------------------------------------------------
1 |  'bitkk',
15 |             'name' => 'bitkk',
16 |             'comment' => 'a Chinese ZB clone',
17 |             'urls' => array (
18 |                 'api' => array (
19 |                     'public' => 'http://api.bitkk.com/data', // no https for public API
20 |                     'private' => 'https://trade.bitkk.com/api',
21 |                 ),
22 |                 'www' => 'https://www.bitkk.com',
23 |                 'doc' => 'https://www.bitkk.com/i/developer',
24 |                 'fees' => 'https://www.bitkk.com/i/rate',
25 |             ),
26 |         ));
27 |     }
28 | }
29 | 


--------------------------------------------------------------------------------
/php/btcexchange.php:
--------------------------------------------------------------------------------
 1 |  'btcexchange',
15 |             'name' => 'BTCExchange',
16 |             'countries' => array ( 'PH' ), // Philippines
17 |             'rateLimit' => 1500,
18 |             'has' => array (
19 |                 'CORS' => false,
20 |             ),
21 |             'urls' => array (
22 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27993052-4c92911a-64aa-11e7-96d8-ec6ac3435757.jpg',
23 |                 'api' => 'https://www.btcexchange.ph/api',
24 |                 'www' => 'https://www.btcexchange.ph',
25 |                 'doc' => 'https://github.com/BTCTrader/broker-api-docs',
26 |             ),
27 |             'markets' => array (
28 |                 'BTC/PHP' => array ( 'id' => 'BTC/PHP', 'symbol' => 'BTC/PHP', 'base' => 'BTC', 'quote' => 'PHP' ),
29 |             ),
30 |         ));
31 |     }
32 | }
33 | 


--------------------------------------------------------------------------------
/php/chilebit.php:
--------------------------------------------------------------------------------
 1 |  'chilebit',
15 |             'name' => 'ChileBit',
16 |             'countries' => array ( 'CL' ),
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg',
22 |                 'api' => array (
23 |                     'public' => 'https://api.blinktrade.com/api',
24 |                     'private' => 'https://api.blinktrade.com/tapi',
25 |                 ),
26 |                 'www' => 'https://chilebit.net',
27 |                 'doc' => 'https://blinktrade.com/docs',
28 |             ),
29 |             'options' => array (
30 |                 'brokerId' => '9', // https://blinktrade.com/docs/#brokers
31 |             ),
32 |         ));
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/php/coinbaseprime.php:
--------------------------------------------------------------------------------
 1 |  'coinbaseprime',
15 |             'name' => 'Coinbase Prime',
16 |             'urls' => array (
17 |                 'test' => 'https://api-public.sandbox.prime.coinbase.com',
18 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg',
19 |                 'api' => 'https://api.prime.coinbase.com',
20 |                 'www' => 'https://prime.coinbase.com',
21 |                 'doc' => 'https://docs.prime.coinbase.com',
22 |                 'fees' => 'https://support.prime.coinbase.com/customer/en/portal/articles/2945629-fees?b_id=17475',
23 |             ),
24 |         ));
25 |     }
26 | }
27 | 


--------------------------------------------------------------------------------
/php/coinbasepro.php:
--------------------------------------------------------------------------------
 1 |  'coinbasepro',
15 |             'name' => 'Coinbase Pro',
16 |             'urls' => array (
17 |                 'test' => 'https://api-public.sandbox.pro.coinbase.com',
18 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg',
19 |                 'api' => 'https://api.pro.coinbase.com',
20 |                 'www' => 'https://pro.coinbase.com/',
21 |                 'doc' => 'https://docs.pro.coinbase.com/',
22 |                 'fees' => array (
23 |                     'https://docs.pro.coinbase.com/#fees',
24 |                     'https://support.pro.coinbase.com/customer/en/portal/articles/2945310-fees',
25 |                 ),
26 |             ),
27 |         ));
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/php/fybsg.php:
--------------------------------------------------------------------------------
 1 |  'fybsg',
15 |             'name' => 'FYB-SG',
16 |             'countries' => array ( 'SG' ), // Singapore
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27766513-3364d56a-5edb-11e7-9e6b-d5898bb89c81.jpg',
22 |                 'api' => 'https://www.fybsg.com/api/SGD',
23 |                 'www' => 'https://www.fybsg.com',
24 |                 'doc' => 'http://docs.fyb.apiary.io',
25 |             ),
26 |             'markets' => array (
27 |                 'BTC/SGD' => array ( 'id' => 'SGD', 'symbol' => 'BTC/SGD', 'base' => 'BTC', 'quote' => 'SGD' ),
28 |             ),
29 |         ));
30 |     }
31 | }
32 | 


--------------------------------------------------------------------------------
/php/huobicny.php:
--------------------------------------------------------------------------------
 1 |  'huobicny',
15 |             'name' => 'Huobi CNY',
16 |             'hostname' => 'be.huobi.com',
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27766569-15aa7b9a-5edd-11e7-9e7f-44791f4ee49c.jpg',
22 |                 'api' => array (
23 |                     'public' => 'https://be.huobi.com',
24 |                     'private' => 'https://be.huobi.com',
25 |                     'market' => 'https://be.huobi.com',
26 |                 ),
27 |                 'www' => 'https://www.huobi.com',
28 |                 'doc' => 'https://github.com/huobiapi/API_Docs/wiki/REST_api_reference',
29 |             ),
30 |         ));
31 |     }
32 | }
33 | 


--------------------------------------------------------------------------------
/php/qryptos.php:
--------------------------------------------------------------------------------
 1 |  'qryptos',
15 |             'name' => 'QRYPTOS',
16 |         ));
17 |     }
18 | }
19 | 


--------------------------------------------------------------------------------
/php/quoinex.php:
--------------------------------------------------------------------------------
 1 |  'quoinex',
15 |             'name' => 'QUOINEX',
16 |         ));
17 |     }
18 | }
19 | 


--------------------------------------------------------------------------------
/php/surbitcoin.php:
--------------------------------------------------------------------------------
 1 |  'surbitcoin',
15 |             'name' => 'SurBitcoin',
16 |             'countries' => array ( 'VE' ),
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27991511-f0a50194-6481-11e7-99b5-8f02932424cc.jpg',
22 |                 'api' => array (
23 |                     'public' => 'https://api.blinktrade.com/api',
24 |                     'private' => 'https://api.blinktrade.com/tapi',
25 |                 ),
26 |                 'www' => 'https://surbitcoin.com',
27 |                 'doc' => 'https://blinktrade.com/docs',
28 |             ),
29 |             'options' => array (
30 |                 'brokerId' => '1', // https://blinktrade.com/docs/#brokers
31 |             ),
32 |         ));
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/php/test/bootstrap.php:
--------------------------------------------------------------------------------
1 |  false));
22 | }
23 | 


--------------------------------------------------------------------------------
/php/urdubit.php:
--------------------------------------------------------------------------------
 1 |  'urdubit',
15 |             'name' => 'UrduBit',
16 |             'countries' => array ( 'PK' ),
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27991453-156bf3ae-6480-11e7-82eb-7295fe1b5bb4.jpg',
22 |                 'api' => array (
23 |                     'public' => 'https://api.blinktrade.com/api',
24 |                     'private' => 'https://api.blinktrade.com/tapi',
25 |                 ),
26 |                 'www' => 'https://urdubit.com',
27 |                 'doc' => 'https://blinktrade.com/docs',
28 |             ),
29 |             'options' => array (
30 |                 'brokerId' => '8', // https://blinktrade.com/docs/#brokers
31 |             ),
32 |         ));
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/php/vbtc.php:
--------------------------------------------------------------------------------
 1 |  'vbtc',
15 |             'name' => 'VBTC',
16 |             'countries' => array ( 'VN' ),
17 |             'has' => array (
18 |                 'CORS' => false,
19 |             ),
20 |             'urls' => array (
21 |                 'logo' => 'https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg',
22 |                 'api' => array (
23 |                     'public' => 'https://api.blinktrade.com/api',
24 |                     'private' => 'https://api.blinktrade.com/tapi',
25 |                 ),
26 |                 'www' => 'https://vbtc.exchange',
27 |                 'doc' => 'https://blinktrade.com/docs',
28 |             ),
29 |             'options' => array (
30 |                 'brokerId' => '3', // https://blinktrade.com/docs/#brokers
31 |             ),
32 |         ));
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
13 | 
14 |     
15 |         
16 |             php/test
17 |         
18 |     
19 | 
20 |     
21 |         
22 |             php
23 |         
24 |     
25 | 
26 |     
27 |         
28 |     
29 | 
30 | 


--------------------------------------------------------------------------------
/postinstall.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | console.log ('                                                                 ')
 4 | console.log ('              ---------------------------------------------------')
 5 | console.log ('                                                                 ')
 6 | console.log ('                     You can contribute in crypto directly:      ')
 7 | console.log ('                                                                 ')
 8 | console.log ('                 ETH 0xa7c2b18b7c8b86984560cad3b1bc3224b388ded0  ')
 9 | console.log ('                 BTC 33RmVRfhK2WZVQR1R83h2e9yXoqRNDvJva          ')
10 | console.log ('                 BCH 1GN9p233TvNcNQFthCgfiHUnj5JRKEc2Ze          ')
11 | console.log ('                 LTC LbT8mkAqQBphc4yxLXEDgYDfEax74et3bP          ')
12 | console.log ('                                                                 ')
13 | console.log ('              ---------------------------------------------------')
14 | console.log ('                                                                 ')
15 | console.log ('                                   Thank you!                    ')
16 | console.log ('                                                                 ')


--------------------------------------------------------------------------------
/push-wiki.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | cd ccxt.wiki
 4 | cp ../wiki/FAQ.md .
 5 | cp ../wiki/Certification.md .
 6 | cp ../wiki/Manual.md .
 7 | cp ../wiki/README.md ./Home.md
 8 | cp ../wiki/Exchange-Markets.md .
 9 | cp ../wiki/Exchange-Markets-By-Country.md .
10 | cp ../wiki/Install.md .
11 | git config --global user.email "travis@travis-ci.org"
12 | git config --global user.name "Travis CI"
13 | git commit -a -m ${COMMIT_MESSAGE}
14 | git remote remove origin
15 | git remote add origin https://${GITHUB_TOKEN}@github.com/ccxt/ccxt.wiki.git
16 | git push origin HEAD:master
17 | 


--------------------------------------------------------------------------------
/push.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | LAST_COMMIT_MESSAGE="$(git log --no-merges -1 --pretty=%B)"
 4 | git config --global user.email "travis@travis-ci.org"
 5 | git config --global user.name "Travis CI"
 6 | git add --force build/ccxt.browser.js
 7 | git commit -a -m "${COMMIT_MESSAGE}" -m '[ci skip]'
 8 | git tag -a "${COMMIT_MESSAGE}" -m "${LAST_COMMIT_MESSAGE}" -m "" -m "[ci skip]"
 9 | git remote remove origin
10 | git remote add origin https://${GITHUB_TOKEN}@github.com/ccxt/ccxt.git
11 | git push origin --tags HEAD:master
12 | 


--------------------------------------------------------------------------------
/python/MANIFEST.in:
--------------------------------------------------------------------------------
1 | # Include the license file
2 | include LICENSE.txt
3 | 
4 | # Include the package.json file
5 | include package.json


--------------------------------------------------------------------------------
/python/ccxt/async_support/base/throttle.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | from asyncio import Queue, sleep, Future, ensure_future, get_event_loop
 4 | from time import time
 5 | 
 6 | __all__ = [
 7 |     'throttle',
 8 | ]
 9 | 
10 | 
11 | def throttle(config=None):
12 | 
13 |     cfg = {
14 |         'lastTimestamp': time(),
15 |         'numTokens': 0,
16 |         'running': False,
17 |         'queue': Queue(),
18 |         'loop': get_event_loop(),
19 |         'delay': 0.001,
20 |         'refillRate': 0.001,
21 |         'defaultCost': 1.000,
22 |         'capacity': 1.000,
23 |     }
24 | 
25 |     cfg.update(config)
26 | 
27 |     async def run():
28 |         if not cfg['running']:
29 |             cfg['running'] = True
30 |             while not cfg['queue'].empty():
31 |                 now = time()
32 |                 elapsed = (now - cfg['lastTimestamp'])
33 |                 cfg['lastTimestamp'] = now
34 |                 cfg['numTokens'] = min(cfg['capacity'], cfg['numTokens'] + elapsed * cfg['refillRate'] * 1000)
35 |                 if cfg['numTokens'] > 0:
36 |                     if not cfg['queue'].empty():
37 |                         cost, future = cfg['queue'].get_nowait()
38 |                         cfg['numTokens'] -= (cost if cost else cfg['defaultCost'])
39 |                         if not future.done():
40 |                             future.set_result(None)
41 |                 await sleep(cfg['delay'])
42 |             cfg['running'] = False
43 | 
44 |     def throttle(cost=None):
45 |         future = Future()
46 |         cfg['queue'].put_nowait((cost, future))
47 |         ensure_future(run())
48 |         return future
49 | 
50 |     return throttle
51 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/bitkk.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.zb import zb
 7 | 
 8 | 
 9 | class bitkk (zb):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(bitkk, self).describe(), {
13 |             'id': 'bitkk',
14 |             'name': 'bitkk',
15 |             'comment': 'a Chinese ZB clone',
16 |             'urls': {
17 |                 'api': {
18 |                     'public': 'http://api.bitkk.com/data',  # no https for public API
19 |                     'private': 'https://trade.bitkk.com/api',
20 |                 },
21 |                 'www': 'https://www.bitkk.com',
22 |                 'doc': 'https://www.bitkk.com/i/developer',
23 |                 'fees': 'https://www.bitkk.com/i/rate',
24 |             },
25 |         })
26 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/btcexchange.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.btcturk import btcturk
 7 | 
 8 | 
 9 | class btcexchange (btcturk):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(btcexchange, self).describe(), {
13 |             'id': 'btcexchange',
14 |             'name': 'BTCExchange',
15 |             'countries': ['PH'],  # Philippines
16 |             'rateLimit': 1500,
17 |             'has': {
18 |                 'CORS': False,
19 |             },
20 |             'urls': {
21 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27993052-4c92911a-64aa-11e7-96d8-ec6ac3435757.jpg',
22 |                 'api': 'https://www.btcexchange.ph/api',
23 |                 'www': 'https://www.btcexchange.ph',
24 |                 'doc': 'https://github.com/BTCTrader/broker-api-docs',
25 |             },
26 |             'markets': {
27 |                 'BTC/PHP': {'id': 'BTC/PHP', 'symbol': 'BTC/PHP', 'base': 'BTC', 'quote': 'PHP'},
28 |             },
29 |         })
30 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/chilebit.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.foxbit import foxbit
 7 | 
 8 | 
 9 | class chilebit (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(chilebit, self).describe(), {
13 |             'id': 'chilebit',
14 |             'name': 'ChileBit',
15 |             'countries': ['CL'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://chilebit.net',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '9',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/coinbaseprime.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.gdax import gdax
 7 | 
 8 | 
 9 | class coinbaseprime (gdax):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(coinbaseprime, self).describe(), {
13 |             'id': 'coinbaseprime',
14 |             'name': 'Coinbase Prime',
15 |             'urls': {
16 |                 'test': 'https://api-public.sandbox.prime.coinbase.com',
17 |                 'logo': 'https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg',
18 |                 'api': 'https://api.prime.coinbase.com',
19 |                 'www': 'https://prime.coinbase.com',
20 |                 'doc': 'https://docs.prime.coinbase.com',
21 |                 'fees': 'https://support.prime.coinbase.com/customer/en/portal/articles/2945629-fees?b_id=17475',
22 |             },
23 |         })
24 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/coinbasepro.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.gdax import gdax
 7 | 
 8 | 
 9 | class coinbasepro (gdax):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(coinbasepro, self).describe(), {
13 |             'id': 'coinbasepro',
14 |             'name': 'Coinbase Pro',
15 |             'urls': {
16 |                 'test': 'https://api-public.sandbox.pro.coinbase.com',
17 |                 'logo': 'https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg',
18 |                 'api': 'https://api.pro.coinbase.com',
19 |                 'www': 'https://pro.coinbase.com/',
20 |                 'doc': 'https://docs.pro.coinbase.com/',
21 |                 'fees': [
22 |                     'https://docs.pro.coinbase.com/#fees',
23 |                     'https://support.pro.coinbase.com/customer/en/portal/articles/2945310-fees',
24 |                 ],
25 |             },
26 |         })
27 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/fybsg.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.fybse import fybse
 7 | 
 8 | 
 9 | class fybsg (fybse):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(fybsg, self).describe(), {
13 |             'id': 'fybsg',
14 |             'name': 'FYB-SG',
15 |             'countries': ['SG'],  # Singapore
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766513-3364d56a-5edb-11e7-9e6b-d5898bb89c81.jpg',
21 |                 'api': 'https://www.fybsg.com/api/SGD',
22 |                 'www': 'https://www.fybsg.com',
23 |                 'doc': 'http://docs.fyb.apiary.io',
24 |             },
25 |             'markets': {
26 |                 'BTC/SGD': {'id': 'SGD', 'symbol': 'BTC/SGD', 'base': 'BTC', 'quote': 'SGD'},
27 |             },
28 |         })
29 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/huobicny.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.huobipro import huobipro
 7 | 
 8 | 
 9 | class huobicny (huobipro):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(huobicny, self).describe(), {
13 |             'id': 'huobicny',
14 |             'name': 'Huobi CNY',
15 |             'hostname': 'be.huobi.com',
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766569-15aa7b9a-5edd-11e7-9e7f-44791f4ee49c.jpg',
21 |                 'api': {
22 |                     'public': 'https://be.huobi.com',
23 |                     'private': 'https://be.huobi.com',
24 |                     'market': 'https://be.huobi.com',
25 |                 },
26 |                 'www': 'https://www.huobi.com',
27 |                 'doc': 'https://github.com/huobiapi/API_Docs/wiki/REST_api_reference',
28 |             },
29 |         })
30 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/jubi.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.btcbox import btcbox
 7 | 
 8 | 
 9 | class jubi (btcbox):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(jubi, self).describe(), {
13 |             'id': 'jubi',
14 |             'name': 'jubi.com',
15 |             'countries': ['CN'],
16 |             'rateLimit': 1500,
17 |             'version': 'v1',
18 |             'has': {
19 |                 'CORS': False,
20 |                 'fetchTickers': True,
21 |             },
22 |             'urls': {
23 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766581-9d397d9a-5edd-11e7-8fb9-5d8236c0e692.jpg',
24 |                 'api': 'https://www.jubi.com/api',
25 |                 'www': 'https://www.jubi.com',
26 |                 'doc': 'https://www.jubi.com/help/api.html',
27 |             },
28 |         })
29 | 
30 |     async def fetch_markets(self):
31 |         markets = await self.publicGetAllticker()
32 |         keys = list(markets.keys())
33 |         result = []
34 |         for p in range(0, len(keys)):
35 |             id = keys[p]
36 |             base = id.upper()
37 |             quote = 'CNY'  # todo
38 |             symbol = base + '/' + quote
39 |             base = self.common_currency_code(base)
40 |             quote = self.common_currency_code(quote)
41 |             result.append({
42 |                 'id': id,
43 |                 'symbol': symbol,
44 |                 'base': base,
45 |                 'quote': quote,
46 |                 'info': id,
47 |             })
48 |         return result
49 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/qryptos.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.liquid import liquid
 7 | 
 8 | 
 9 | class qryptos (liquid):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(qryptos, self).describe(), {
13 |             'id': 'qryptos',
14 |             'name': 'QRYPTOS',
15 |         })
16 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/quoinex.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.liquid import liquid
 7 | 
 8 | 
 9 | class quoinex (liquid):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(quoinex, self).describe(), {
13 |             'id': 'quoinex',
14 |             'name': 'QUOINEX',
15 |         })
16 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/surbitcoin.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.foxbit import foxbit
 7 | 
 8 | 
 9 | class surbitcoin (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(surbitcoin, self).describe(), {
13 |             'id': 'surbitcoin',
14 |             'name': 'SurBitcoin',
15 |             'countries': ['VE'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991511-f0a50194-6481-11e7-99b5-8f02932424cc.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://surbitcoin.com',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '1',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/urdubit.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.foxbit import foxbit
 7 | 
 8 | 
 9 | class urdubit (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(urdubit, self).describe(), {
13 |             'id': 'urdubit',
14 |             'name': 'UrduBit',
15 |             'countries': ['PK'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991453-156bf3ae-6480-11e7-82eb-7295fe1b5bb4.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://urdubit.com',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '8',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/async_support/vbtc.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.async_support.foxbit import foxbit
 7 | 
 8 | 
 9 | class vbtc (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(vbtc, self).describe(), {
13 |             'id': 'vbtc',
14 |             'name': 'VBTC',
15 |             'countries': ['VN'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://vbtc.exchange',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '3',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/bitkk.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.zb import zb
 7 | 
 8 | 
 9 | class bitkk (zb):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(bitkk, self).describe(), {
13 |             'id': 'bitkk',
14 |             'name': 'bitkk',
15 |             'comment': 'a Chinese ZB clone',
16 |             'urls': {
17 |                 'api': {
18 |                     'public': 'http://api.bitkk.com/data',  # no https for public API
19 |                     'private': 'https://trade.bitkk.com/api',
20 |                 },
21 |                 'www': 'https://www.bitkk.com',
22 |                 'doc': 'https://www.bitkk.com/i/developer',
23 |                 'fees': 'https://www.bitkk.com/i/rate',
24 |             },
25 |         })
26 | 


--------------------------------------------------------------------------------
/python/ccxt/btcexchange.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.btcturk import btcturk
 7 | 
 8 | 
 9 | class btcexchange (btcturk):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(btcexchange, self).describe(), {
13 |             'id': 'btcexchange',
14 |             'name': 'BTCExchange',
15 |             'countries': ['PH'],  # Philippines
16 |             'rateLimit': 1500,
17 |             'has': {
18 |                 'CORS': False,
19 |             },
20 |             'urls': {
21 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27993052-4c92911a-64aa-11e7-96d8-ec6ac3435757.jpg',
22 |                 'api': 'https://www.btcexchange.ph/api',
23 |                 'www': 'https://www.btcexchange.ph',
24 |                 'doc': 'https://github.com/BTCTrader/broker-api-docs',
25 |             },
26 |             'markets': {
27 |                 'BTC/PHP': {'id': 'BTC/PHP', 'symbol': 'BTC/PHP', 'base': 'BTC', 'quote': 'PHP'},
28 |             },
29 |         })
30 | 


--------------------------------------------------------------------------------
/python/ccxt/chilebit.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.foxbit import foxbit
 7 | 
 8 | 
 9 | class chilebit (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(chilebit, self).describe(), {
13 |             'id': 'chilebit',
14 |             'name': 'ChileBit',
15 |             'countries': ['CL'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991414-1298f0d8-647f-11e7-9c40-d56409266336.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://chilebit.net',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '9',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/coinbaseprime.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.gdax import gdax
 7 | 
 8 | 
 9 | class coinbaseprime (gdax):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(coinbaseprime, self).describe(), {
13 |             'id': 'coinbaseprime',
14 |             'name': 'Coinbase Prime',
15 |             'urls': {
16 |                 'test': 'https://api-public.sandbox.prime.coinbase.com',
17 |                 'logo': 'https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg',
18 |                 'api': 'https://api.prime.coinbase.com',
19 |                 'www': 'https://prime.coinbase.com',
20 |                 'doc': 'https://docs.prime.coinbase.com',
21 |                 'fees': 'https://support.prime.coinbase.com/customer/en/portal/articles/2945629-fees?b_id=17475',
22 |             },
23 |         })
24 | 


--------------------------------------------------------------------------------
/python/ccxt/coinbasepro.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.gdax import gdax
 7 | 
 8 | 
 9 | class coinbasepro (gdax):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(coinbasepro, self).describe(), {
13 |             'id': 'coinbasepro',
14 |             'name': 'Coinbase Pro',
15 |             'urls': {
16 |                 'test': 'https://api-public.sandbox.pro.coinbase.com',
17 |                 'logo': 'https://user-images.githubusercontent.com/1294454/41764625-63b7ffde-760a-11e8-996d-a6328fa9347a.jpg',
18 |                 'api': 'https://api.pro.coinbase.com',
19 |                 'www': 'https://pro.coinbase.com/',
20 |                 'doc': 'https://docs.pro.coinbase.com/',
21 |                 'fees': [
22 |                     'https://docs.pro.coinbase.com/#fees',
23 |                     'https://support.pro.coinbase.com/customer/en/portal/articles/2945310-fees',
24 |                 ],
25 |             },
26 |         })
27 | 


--------------------------------------------------------------------------------
/python/ccxt/fybsg.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.fybse import fybse
 7 | 
 8 | 
 9 | class fybsg (fybse):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(fybsg, self).describe(), {
13 |             'id': 'fybsg',
14 |             'name': 'FYB-SG',
15 |             'countries': ['SG'],  # Singapore
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766513-3364d56a-5edb-11e7-9e6b-d5898bb89c81.jpg',
21 |                 'api': 'https://www.fybsg.com/api/SGD',
22 |                 'www': 'https://www.fybsg.com',
23 |                 'doc': 'http://docs.fyb.apiary.io',
24 |             },
25 |             'markets': {
26 |                 'BTC/SGD': {'id': 'SGD', 'symbol': 'BTC/SGD', 'base': 'BTC', 'quote': 'SGD'},
27 |             },
28 |         })
29 | 


--------------------------------------------------------------------------------
/python/ccxt/huobicny.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.huobipro import huobipro
 7 | 
 8 | 
 9 | class huobicny (huobipro):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(huobicny, self).describe(), {
13 |             'id': 'huobicny',
14 |             'name': 'Huobi CNY',
15 |             'hostname': 'be.huobi.com',
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766569-15aa7b9a-5edd-11e7-9e7f-44791f4ee49c.jpg',
21 |                 'api': {
22 |                     'public': 'https://be.huobi.com',
23 |                     'private': 'https://be.huobi.com',
24 |                     'market': 'https://be.huobi.com',
25 |                 },
26 |                 'www': 'https://www.huobi.com',
27 |                 'doc': 'https://github.com/huobiapi/API_Docs/wiki/REST_api_reference',
28 |             },
29 |         })
30 | 


--------------------------------------------------------------------------------
/python/ccxt/jubi.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.btcbox import btcbox
 7 | 
 8 | 
 9 | class jubi (btcbox):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(jubi, self).describe(), {
13 |             'id': 'jubi',
14 |             'name': 'jubi.com',
15 |             'countries': ['CN'],
16 |             'rateLimit': 1500,
17 |             'version': 'v1',
18 |             'has': {
19 |                 'CORS': False,
20 |                 'fetchTickers': True,
21 |             },
22 |             'urls': {
23 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27766581-9d397d9a-5edd-11e7-8fb9-5d8236c0e692.jpg',
24 |                 'api': 'https://www.jubi.com/api',
25 |                 'www': 'https://www.jubi.com',
26 |                 'doc': 'https://www.jubi.com/help/api.html',
27 |             },
28 |         })
29 | 
30 |     def fetch_markets(self):
31 |         markets = self.publicGetAllticker()
32 |         keys = list(markets.keys())
33 |         result = []
34 |         for p in range(0, len(keys)):
35 |             id = keys[p]
36 |             base = id.upper()
37 |             quote = 'CNY'  # todo
38 |             symbol = base + '/' + quote
39 |             base = self.common_currency_code(base)
40 |             quote = self.common_currency_code(quote)
41 |             result.append({
42 |                 'id': id,
43 |                 'symbol': symbol,
44 |                 'base': base,
45 |                 'quote': quote,
46 |                 'info': id,
47 |             })
48 |         return result
49 | 


--------------------------------------------------------------------------------
/python/ccxt/qryptos.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.liquid import liquid
 7 | 
 8 | 
 9 | class qryptos (liquid):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(qryptos, self).describe(), {
13 |             'id': 'qryptos',
14 |             'name': 'QRYPTOS',
15 |         })
16 | 


--------------------------------------------------------------------------------
/python/ccxt/quoinex.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.liquid import liquid
 7 | 
 8 | 
 9 | class quoinex (liquid):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(quoinex, self).describe(), {
13 |             'id': 'quoinex',
14 |             'name': 'QUOINEX',
15 |         })
16 | 


--------------------------------------------------------------------------------
/python/ccxt/surbitcoin.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.foxbit import foxbit
 7 | 
 8 | 
 9 | class surbitcoin (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(surbitcoin, self).describe(), {
13 |             'id': 'surbitcoin',
14 |             'name': 'SurBitcoin',
15 |             'countries': ['VE'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991511-f0a50194-6481-11e7-99b5-8f02932424cc.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://surbitcoin.com',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '1',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/urdubit.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.foxbit import foxbit
 7 | 
 8 | 
 9 | class urdubit (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(urdubit, self).describe(), {
13 |             'id': 'urdubit',
14 |             'name': 'UrduBit',
15 |             'countries': ['PK'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991453-156bf3ae-6480-11e7-82eb-7295fe1b5bb4.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://urdubit.com',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '8',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/ccxt/vbtc.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
 4 | # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
 5 | 
 6 | from ccxt.foxbit import foxbit
 7 | 
 8 | 
 9 | class vbtc (foxbit):
10 | 
11 |     def describe(self):
12 |         return self.deep_extend(super(vbtc, self).describe(), {
13 |             'id': 'vbtc',
14 |             'name': 'VBTC',
15 |             'countries': ['VN'],
16 |             'has': {
17 |                 'CORS': False,
18 |             },
19 |             'urls': {
20 |                 'logo': 'https://user-images.githubusercontent.com/1294454/27991481-1f53d1d8-6481-11e7-884e-21d17e7939db.jpg',
21 |                 'api': {
22 |                     'public': 'https://api.blinktrade.com/api',
23 |                     'private': 'https://api.blinktrade.com/tapi',
24 |                 },
25 |                 'www': 'https://vbtc.exchange',
26 |                 'doc': 'https://blinktrade.com/docs',
27 |             },
28 |             'options': {
29 |                 'brokerId': '3',  # https://blinktrade.com/docs/#brokers
30 |             },
31 |         })
32 | 


--------------------------------------------------------------------------------
/python/deploy.sh:
--------------------------------------------------------------------------------
1 | python setup.py sdist bdist_wheel
2 | twine upload dist/* -u x84 -p ${PYPI_PASSWORD}


--------------------------------------------------------------------------------
/python/setup.cfg:
--------------------------------------------------------------------------------
 1 | [bdist_wheel]
 2 | # This flag says that the code is written to work on both Python 2 and Python
 3 | # 3. If at all possible, it is good practice to do this. If you cannot, you
 4 | # will need to generate wheels for each Python version that you support.
 5 | universal=1
 6 | 
 7 | [flake8]
 8 | ignore = E501
 9 | exclude =
10 |     .ropeproject,
11 |     .tox,
12 |     .eggs,
13 |     # No need to traverse our git directory
14 |     .git,
15 |     # There's no value in checking cache directories
16 |     __pycache__,
17 |     # Other special cases
18 |     node_modules,
19 |     .nyc_output,
20 |     build,
21 |     tmp,
22 |     # No need to check the basecode
23 |     ccxt.py
24 | 


--------------------------------------------------------------------------------
/python/test/test_calculate_fee.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # THIS IS A MOCKUP FILE IN PROGRESS
 4 | 
 5 | # import argparse
 6 | import os
 7 | import sys
 8 | # import json
 9 | # import time
10 | 
11 | # ------------------------------------------------------------------------------
12 | 
13 | root = os.path.dirname(os.path.abspath(__file__))
14 | sys.path.append(root)
15 | 
16 | # ------------------------------------------------------------------------------
17 | 
18 | import ccxt  # noqa: E402
19 | 
20 | # ------------------------------------------------------------------------------
21 | 
22 | taker = 0.0025
23 | maker = 0.0010
24 | price = 100.00
25 | amount = 10.00
26 | 
27 | market = {
28 |     'id': 'foobar',
29 |     'symbol': 'FOO/BAR',
30 |     'base': 'FOO',
31 |     'quote': 'BAR',
32 |     'taker': taker,
33 |     'maker': maker,
34 | }
35 | 
36 | exchange = ccxt.Exchange({
37 |     'id': 'mock',
38 |     'markets': {'FOO/BAR': market},
39 | })
40 | 
41 | exchange.calculate_fee(market['symbol'], 'limit', 'sell', amount, price, 'taker', {})
42 | 
43 | # {'rate': {'quote': 0.0025, 'base': 0.0}, 'cost': {'quote': 2.5, 'base': 0.0}}
44 | 
45 | exchange.calculate_fee(market['symbol'], 'limit', 'sell', amount, price, 'maker', {})
46 | 
47 | # {'rate': {'quote': 0.001, 'base': 0.0}, 'cost': {'quote': 1.0, 'base': 0.0}}
48 | 


--------------------------------------------------------------------------------
/python/test/test_deep_extend.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | # THIS IS A MOCKUP FILE IN PROGRESS
 4 | 
 5 | # import argparse
 6 | import os
 7 | import sys
 8 | from pprint import pprint
 9 | # import json
10 | # import time
11 | 
12 | # ------------------------------------------------------------------------------
13 | 
14 | root = os.path.dirname(os.path.abspath(__file__))
15 | sys.path.append(root)
16 | 
17 | # ------------------------------------------------------------------------------
18 | 
19 | import ccxt  # noqa: E402
20 | 
21 | # ------------------------------------------------------------------------------
22 | 
23 | values = [
24 |     {
25 |         'a': 1,
26 |         'b': 2,
27 |         'd': {
28 |             'a': 1,
29 |             'b': [],
30 |             'c': {'test1': 123, 'test2': 321}},
31 |         'f': 5,
32 |         'g': 123,
33 |         'i': 321,
34 |         'j': [1, 2],
35 |     },
36 |     {
37 |         'b': 3,
38 |         'c': 5,
39 |         'd': {
40 |             'b': {'first': 'one', 'second': 'two'},
41 |             'c': {'test2': 222}},
42 |         'e': {'one': 1, 'two': 2},
43 |         'f': [{'foo': 'bar'}],
44 |         'g': None,
45 |         'h': r'abc',
46 |         'i': None,
47 |         'j': [3, 4]
48 |     }
49 | ]
50 | 
51 | pprint(ccxt.Exchange.deep_extend(*values))
52 | 
53 | # assert.deepEqual ({
54 | #     a: 1,
55 | #     b: 3,
56 | #     d: {
57 | #         a: 1,
58 | #         b: {first: 'one', second: 'two'},
59 | #         c: {test1: 123, test2: 222}
60 | #     },
61 | #     f: [{'foo': 'bar'}],
62 | #     g: undefined,
63 | #     c: 5,
64 | #     e: {one: 1, two: 2},
65 | #     h: /abc/g,
66 | #     i: null,
67 | #     j: [3, 4]
68 | # }, extended)
69 | 


--------------------------------------------------------------------------------
/python/tox.ini:
--------------------------------------------------------------------------------
 1 | [tox]
 2 | envlist = py{27,35,36},qa
 3 | skipsdist = True
 4 | skip_missing_interpreters = True
 5 | 
 6 | [testenv]
 7 | setenv =
 8 |     PYTHONPATH = {toxinidir}:{toxinidir}
 9 | commands =
10 |     python test.py
11 | 
12 | [testenv:qa]
13 | basepython = python3
14 | changedir=..
15 | commands = flake8
16 | deps = .[qa]
17 | 
18 | [testenv:doc]
19 | changedir=../doc
20 | deps = .[doc]
21 | commands=
22 |     sphinx-build -W -b html -d {envtmpdir}/doctrees .  {envtmpdir}/html
23 | 


--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
 1 | [flake8]
 2 | ignore = E501
 3 | exclude =
 4 |     .ropeproject,
 5 |     .tox,
 6 |     .eggs,
 7 |     # No need to traverse our git directory
 8 |     .git,
 9 |     # There's no value in checking cache directories
10 |     __pycache__,
11 |     # Other special cases
12 |     node_modules,
13 |     .nyc_output,
14 |     build,
15 |     tmp,
16 |     # No need to check the basecode
17 |     ccxt.py
18 | 


--------------------------------------------------------------------------------
/wiki/Certification.md:
--------------------------------------------------------------------------------
1 | # CCXT Certification Program · ![CCXT Certified](https://img.shields.io/badge/CCXT-certified-green.svg)
2 | 
3 | The structure of CCXT defines a good, portable and cross-compatible standard for exchanges' API interfaces, that is implemented in the CCXT Unified API. Exchanges are welcome to apply for our certification program. Certification is technically supervised and quality-assured by members of the CCXT Dev Team. That implies that an exchange having a "certified" badge is properly implemented and tested by the authors of CCXT. Certification means less bugs, more functionality, priority support and a much more stable and efficient implementation in general.
4 | 
5 | ## Contact Us
6 | 
7 | For inquiries on getting your exchange integrated, listed and certified: info@ccxt.trade
8 | 


--------------------------------------------------------------------------------