Skip to content

Exchange Operations

Chris Priest edited this page Nov 6, 2017 · 1 revision

Exchange operations

Get current price

This gets the current exchange rate between any cryptocurrency and any fiat currency.

command line examples:

$ moneywagon current-price ltc eur
3.798

Additionally, you can include --verbose to get more output:

$ moneywagon current-price btc usd --verbose
* Trying: <Service: Bitstamp (0 in cache)>
URL: https://www.bitstamp.net/api/ticker/
279.01

>>> from moneywagon import Bittrex
>>> b = Bittrex()
>>> b.get_current_price('ltc', 'btc')
0.01619

Make Order

This example buys 0.05 worth of LTC with bitcoin at 0.1386 LTC/BTC. Returned is the "order ID" which can then be used to cancel order.

Supported by the following exchanges: GDAX, Poloniex, Bittrex, NovaExchange

>>> from moneywagon.services import GDAX
>>> g = GDAX(api_key='91ead6e3308a4daa...', api_secret='3617806dc4b...', api_pass='3dfr38s...')
>>> g.make_order('ltc', 'btc', 0.05, 0.13860113, side="buy")
'b1c95c62-2f81-4005-b19c-80608c30d543'

Cancel order

>>> from moneywagon.services import GDAX
>>> g = GDAX(api_key='91ead6e3308a4daa...', api_secret='3617806dc4b...')
>>> g.cancel_order('b1c95c62-2f81-4005-b19c-80608c30d543')

List orders

This lists all orders you have made. Proper authentication credentials are required for this endpoint. To get all orders for an exchange, use the get_orderbook endpoint instead.

>>> from moneywagon.services import GDAX
>>> g = GDAX(api_key='91ead6e3308a4daa...', api_secret='3617806dc4b...', api_pass='3dfr38s...')
>>> g.list_orders()
[{u'created_at': u'2017-07-05T16:00:53.70265Z',
  u'executed_value': u'0.0000000000000000',
  u'fill_fees': u'0.0000000000000000',
  u'filled_size': u'0.00000000',
  u'id': u'0ed4825c-d703-4aa8-aca4-0807bd76b6cd',
  u'post_only': True,
  u'price': u'1000.00000000',
  u'product_id': u'BTC-USD',
  u'settled': False,
  u'side': u'buy',
  u'size': u'0.30000000',
  u'status': u'open',
  u'stp': u'dc',
  u'time_in_force': u'GTC',
  u'type': u'limit'}
]

Note: Moneywagon does not yet convert open orders to a unified format across all exchanges. Each individual exchange will return this data in a unique format.

Initiate withdraw

>>> n = NovaExchange(api_pass='dg38dh3...', api_key='dhwbjfi438shjf...')
>>> n.withdraw('dash', 0.05, 'XmgKAkuZAT6vnunfCX9ewQ6vv8DQGJXamV')
{u'address': u'XmgKAkuZAT6vnunfCX9ewQ6vv8DQGJXamV',
u'amount': u'0.05000000',
u'amount_after_withdraw': u'0.10934224',
u'amount_before_withdraw': u'0.15934224',
u'amount_in_orders': u'0.00000000',
u'amount_sent': u'0.04980000',
u'currency': u'DASH',
u'message': u'Withdrawal requested successfully',
u'status': u'success',
u'tx_fee': u'0.00020000',
u'wd_fee': u'0.00000000'}

The output format of this method is not yet unified amongst all exchange implementations.

Get deposit address

>>> n = NovaExchange(api_pass='dg38dh3...', api_key='dhwbjfi438shjf...')
>>> n.get_deposit_address('dash')
u'XqGnkQPntNvshNt5qvfHnGYfjPuJWfYGLU'

Get all supported markets

Use the get_pairs() method to return a list of all pairs supported by the given service. Always returns lowercase identifiers. Crypto identifier is shown first, then a dash character, then the fiat currency identifier.

>>> from moneywagon.services import Poloniex
>>> p = Poloniex()
>>> p.get_pairs()
[u'rep-usd',
 u'xvc-btc',
 u'pink-btc',
 u'sys-btc',
 u'emc2-btc',
 u'rads-btc',
 ...
]

Utilities

>>> from moneywagon import guess_currency_from_address
>>> guess_currency_from_address("NJwRrtKcv3ggkwh3j3yka69rH3x5d5gu5m")
[['nmc', 'Namecoin']]
>>> guess_currency_from_address("1Ng3mALXCEphwLqTZ4x5DutMcRTxpTF299")
[['btc', 'Bitcoin']]
>>> guess_currency_from_address("EMZSp8Q3MGHZmjhSBvh52r6igstTDo4Jzx")
[['emc', 'Emercoin'], ['erc', 'Europecoin']]

This can be used as an address verifier, as an exception gets raised when an invalid address is passed in.

Low level API

The get_current_price function tries multiple services until it find one that returns a result. If you would rather just use one service with no automatic retrying, use the low level 'service' API:

>>> from moneywagon.services import BTER
>>> service = BTER()
>>> service.get_current_price('btc', 'usd')
391.324

Not all services will have every single possible function defined:

>>> service.get_historical_transactions('btc', 'blah')
** NotImplementedError: This service does not support getting historical_transactions.
Or rather it has no defined 'get_historical_transactions' method.

BTER is an exchange, not a block explorer, so it does not have a public API endpoint for getting historical transactions. Most bock explorers don't have current price functionalities, etc.

If you use the CurrentPrice class, the action method will try all services until a value is returned (same as the high level API). If you use a service class that is limited to one API service, such as "BTER", then only that service will be called.

You can also pass in a list of services classes to get more control of which services will be used:

>>> from moneywagon.services import BTCE, Bitstamp
>>> from moneywagon import CurrentPrice
>>> service = CurrentPrice(services=[BTCE, Bitstamp])
>>> service.action('btc', 'usd')
(377.2, 'btce')

Caching considerations

The high level API does not do any caching of any sort. Each call to get_current_price will result in a request with fresh results. On the other hand, the low level API will never make the request twice.

For instance, consider the following example:

>>> from moneywagon.services import BTER
>>> service = BTER()
>>> service.get_current_price('ltc', 'rur') # makes two external calls, one for ltc->btc, one for btc->rur
1.33535
>>> service.get_current_price('btc', 'rur') # makes zero external calls (uses btc-> rur result from last call)
1.33535

Note that the BTER exchange does not have a direct orderbook between Litecoin and Russian Ruble. As a result, moneywagon needs to make two separate API calls to get the correct exchange rate. The first one to get the LTC->BTC exchange rate, and the second one to get the BTC->RUR exchange rate. Then the two results are multiplied together to get the LTC -> RUR exchange rate. If your application does a lot of converting at a time, it will be better for performance to use the low level API.

If you keep the original service instance around and make more calls to get_price, it will use the result of previous calls:

>>> service.get_current_price('btc', 'rur') # will make no external calls
17865.4210346

In other words, if you are using the low level API and you want fresh values, you must make a new instance of the service class.

Tools

ExchangeUniverse

This utility represents all supported exchange services.

>>> from moneywagon import ExchangeUniverse
>>> e = ExchangeUniverse(verbose=True)
Got Response: http://api.btc38.com/v1/ticker.php?c=all&mk_type=cny
Got Response: http://api.btc38.com/v1/ticker.php?c=all&mk_type=btc
BTC38 returned error: No JSON object could be decoded
Got Response: https://btc-e.com/api/3/info
BTCE returned error: No JSON object could be decoded
Got Response: http://data.bter.com/api/1/pairs
Got Response: https://api.bitfinex.com/v1/symbols
Got Response: https://api.bitso.com/v3/available_books/
Got Response: https://bittrex.com/api/v1.1/public/getmarkets
Got Response: https://bleutrade.com/api/v2/public/getmarkets
Got Response: https://c-cex.com/t/pairs.json
Got Response: https://www.cryptopia.co.nz/api/GetTradePairs
Got Response: https://api.gdax.com/products
Got Response: https://api.hitbtc.com/api/1/public/symbols
Got Response: https://api.kraken.com/0/public/AssetPairs
Got Response: https://api.liqui.io/api/3/info
Got Response: https://api.livecoin.net/exchange/ticker
LiveCoin returned error: 503 - Temporarily out of service.
Got Response: https://novaexchange.com/remote/v2/markets/
Got Response: https://poloniex.com/public?command=returnTicker
Got Response: https://usecryptos.com/jsonapi/pairs
Got Response: https://api.vircurex.com/api/get_info_for_currency.json
Got Response: https://yobit.net/api/3/info
Got Response: https://yunbi.com/api/v2/markets.json
Got Response: https://cryptottlivewebapi.xbtce.net:8443/api/v1/public/symbol
>>> e.find_pair('doge', 'usd')
{moneywagon.services.YoBit: [u'doge-usd'],
 moneywagon.services.CexIO: [u'doge-usd'],
 moneywagon.services.Vircurex: [u'doge-usd'],
 moneywagon.services.Cryptopia: [u'doge-usd'],
 moneywagon.services.HitBTC: [u'doge-usd']}
>>> len(e.all_cryptos())
1702