[ReleaseCandidate] Module "GrapheneExchange" - Simple Python Trading Interface

Started by xeroc, January 11, 2016, 02:08:31 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

xeroc

For those using this module: Please note that prices are now denoted in 'base'/'quote'. I highly recommend to read the latest release notes and the documentation:
http://python-graphenelib.readthedocs.org/en/latest/

Note that this release is not available via pip

xeroc

The whole thing is documented at
http://python-graphenelib.readthedocs.org/en/latest/
which is a page that is build from the content of docs/* and the comments in the code.

The graphenewsrpc.py file is to talk to the witness node via rpc.
the payload is constructed to follow the JSON syntax for calls properly:
https://github.com/xeroc/python-graphenelib/blob/master/grapheneapi/graphenewsrpc.py#L82-L86

tonyk

I know it is only semi related...

In graphenewsrpc.py

where can I find some explanation/examples etc.

payload in:

def rpcexec(self, payload):

is bothering me right this moment, but general info will be appreciated as well.
Lack of arbitrage is the problem, isn't it. And this 'should' solves it.

iHashFury

Will  add METAEX.BTC too.

Just need some more BTC and BTS.
Plus BTS to rise in price so I can borrow more BTC   ;) +5%

xeroc

Quote from: iHashFury on January 14, 2016, 01:12:31 PM
error:
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
- 1.7.19973
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 13, in <module>
    dex.cancel(o["orderNumber"])
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/exchange.py", line 908, in cancel
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 160, in method
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 146, in rpcexec
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 138, in rpcexec
grapheneapi.grapheneapi.RPCError: 10 assert_exception: Assert Exception
!is_locked():
    {}
    th_a  wallet.cpp:3508 cancel_order


works with unlocked wallet
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
- 1.7.19524
- 1.7.19527
- 1.7.19530
Placing Orders:
- Selling 89541.300000 OPENMUSE for TRADE.MUSE @1.034500
- Buying 68965.500000 TRADE.MUSE with OPENMUSE @0.965500


I should probably do a check for unlocked wallet somewhere ..
Lots of other checks can be added for misconfiguration and similar stuff .. still in release candidate :)

Good to see it working for you now

iHashFury

Exchange bridge market maker running :) with a little BTC - OPENBTC - TRADE.BTC - TRADE.MUSE - OPENMUSE

Thank you again your help,  patience and BOT Xeroc

[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
- 1.7.19973
- 1.7.19974
Placing Orders:
- Selling 0.034526 BTC for TRADE.BTC @1.034500
- Buying 0.034452 TRADE.BTC with BTC @0.965500
- Selling 0.034526 BTC for OPENBTC @1.034500
- Buying 0.034476 OPENBTC with BTC @0.965500
- Selling 0.034476 OPENBTC for TRADE.BTC @1.034500
- Buying 0.034452 TRADE.BTC with OPENBTC @0.965500
- Selling 89541.300000 OPENMUSE for TRADE.MUSE @1.034500
- Buying 68965.500000 TRADE.MUSE with OPENMUSE @0.965500


Markets:
TRADE.MUSE : OPENMUSE
TRADE.BTC : BTC
OPENBTC : BTC
OPENBTC : TRADE.BTC


iHashFury

error:
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
- 1.7.19973
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 13, in <module>
    dex.cancel(o["orderNumber"])
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/exchange.py", line 908, in cancel
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 160, in method
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 146, in rpcexec
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneapi/grapheneapi.py", line 138, in rpcexec
grapheneapi.grapheneapi.RPCError: 10 assert_exception: Assert Exception
!is_locked():
    {}
    th_a  wallet.cpp:3508 cancel_order


works with unlocked wallet
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
- 1.7.19524
- 1.7.19527
- 1.7.19530
Placing Orders:
- Selling 89541.300000 OPENMUSE for TRADE.MUSE @1.034500
- Buying 68965.500000 TRADE.MUSE with OPENMUSE @0.965500


xeroc

Quote from: iHashFury on January 14, 2016, 10:52:20 AM
testing config using MUSE
#: Markets that are of interest for us
watch_markets         = ["OPENMUSE : TRADE.MUSE",
                         ]


but got this error - (I do have open orders on TRADE.MUSE : OPENMUSE)
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 11, in <module>
    for o in orders[m]:
TypeError: list indices must be integers or slices, not dict


the bot should close my open orders and create new orders at 5% spread?
#: place orders at this spread (in percent)
bridge_spread_percent = 5

Yes .. i noticed it too ..

thing is I coded the api too close to what poloniex is doing .. and they change syntax if you have only one market (compared to several markets)
I will definietly change this behavior ..

in the meantime .. just add another market for which you don't have funds ..

//edit: just pushed a new master that should change the behavior so that the bot works on one market as well

iHashFury

testing config using MUSE
#: Markets that are of interest for us
watch_markets         = ["OPENMUSE : TRADE.MUSE",
                         ]


but got this error - (I do have open orders on TRADE.MUSE : OPENMUSE)
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Closing Orders:
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 11, in <module>
    for o in orders[m]:
TypeError: list indices must be integers or slices, not dict


the bot should close my open orders and create new orders at 5% spread?
#: place orders at this spread (in percent)
bridge_spread_percent = 5

kenCode

kenCode@Agorise
Matrix/Keybase/Blurt/Hive: @Agorise
Session: 0525c95e7f37dca6e29ac84fe7030f0bc5f8bcd564207f03c893e47d2a381a2337

iHashFury

one step closer  8)

[jason@i4p python-graphenelib]$ date ; python3 ~/tmp/git/python-graphenelib/scripts/exchange-simpleticker-stats/main.py
Wed 13 Jan 22:47:53 CET 2016

GOLD_BTS
========
- Trade Premium: 24.085%
- Bid Order Premium: 24.081%
- Ask Order Premium: 8.121%
- Spread: 19.024%
- CER premium:  5.26%

BTC_BTS
=======
- Trade Premium: 15.561%
- Bid Order Premium: 20.528%
- Ask Order Premium: 13.149%
- Spread: 8.874%
- CER premium:  5.22%

EUR_BTS
=======
- Trade Premium: 5.071%
- Bid Order Premium: 21.758%
- Ask Order Premium: 5.071%
- Spread: 19.272%
- CER premium:  5.26%

SILVER_BTS
==========
- Trade Premium: 11.765%
- Bid Order Premium: 11.286%
- Ask Order Premium: 3.340%
- Spread: 8.573%
- CER premium:  5.27%

CNY_BTS
=======
- Trade Premium: 4.270%
- Bid Order Premium: 3.073%
- Ask Order Premium: 4.270%
- Spread: 7.299%
- CER premium:  5.26%

kenCode

kenCode@Agorise
Matrix/Keybase/Blurt/Hive: @Agorise
Session: 0525c95e7f37dca6e29ac84fe7030f0bc5f8bcd564207f03c893e47d2a381a2337

iHashFury

Thank you for your help and patience Xeroc

# delete all - start fresh
rm ~/.local/lib/python*
rm python-graphenelib


# install
git clone https://github.com/xeroc/python-graphenelib.git
cd python-graphenlib
make install-user
# Finished processing dependencies for graphenelib==0.2rc5
pip install --user -r requirements.txt graphenelib
# Successfully installed autobahn-0.11.0 ecdsa-0.13 requests-2.9.1 scrypt-0.7.1 txaio-2.2.0 websocket-client-0.35.0


# feed script error
# ImportError: No module named 'numpy'
pip3 install numpy --user
# Successfully installed numpy-1.10.4
# ImportError: No module named 'prettytable'
pip3 install prettytable --user

feed scripts working :)

will now try the simple ticker

cube

ID: bitcube
bitcube is a dedicated witness and committe member. Please vote for bitcube.

xeroc

Could you re-pull from github then do

  make install-user

and try again?

iHashFury

Do I need to open another RPC wallet port to get this bad boy running?

feed port ArchlinuxARM:
206136ms th_a       main.cpp:169                  main                 ] wdata.ws_server: ws://localhost:8090
206165ms th_a       main.cpp:174                  main                 ] wdata.ws_user:  wdata.ws_password: 
206256ms th_a       main.cpp:240                  main                 ] Listening for incoming HTTP RPC requests on 127.0.0.1:8093


installed and feeds working without issues:
[jason@i4p python-graphenelib]$ make install-user
python setup.py install --user
/usr/lib/python3.5/site-packages/setuptools/dist.py:285: UserWarning: Normalizing '0.2-rc5' to '0.2rc5'
  normalized_version,
running install
running bdist_egg
running egg_info
writing top-level names to graphenelib.egg-info/top_level.txt
writing dependency_links to graphenelib.egg-info/dependency_links.txt
writing graphenelib.egg-info/PKG-INFO
reading manifest file 'graphenelib.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'graphenelib.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-armv7l/egg
running install_lib
running build_py
creating build/bdist.linux-armv7l/egg
creating build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/base58.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/memo.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/transactions.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/account.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/dictionary.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/bip38.py -> build/bdist.linux-armv7l/egg/graphenebase
copying build/lib/graphenebase/__init__.py -> build/bdist.linux-armv7l/egg/graphenebase
creating build/bdist.linux-armv7l/egg/grapheneextra
copying build/lib/grapheneextra/proposal.py -> build/bdist.linux-armv7l/egg/grapheneextra
copying build/lib/grapheneextra/__init__.py -> build/bdist.linux-armv7l/egg/grapheneextra
creating build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/graphenewsprotocol.py -> build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/graphenewsrpc.py -> build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/grapheneclient.py -> build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/grapheneapi.py -> build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/graphenews.py -> build/bdist.linux-armv7l/egg/grapheneapi
copying build/lib/grapheneapi/__init__.py -> build/bdist.linux-armv7l/egg/grapheneapi
creating build/bdist.linux-armv7l/egg/grapheneexchange
copying build/lib/grapheneexchange/exchange.py -> build/bdist.linux-armv7l/egg/grapheneexchange
copying build/lib/grapheneexchange/grapheneexchange.py -> build/bdist.linux-armv7l/egg/grapheneexchange
copying build/lib/grapheneexchange/__init__.py -> build/bdist.linux-armv7l/egg/grapheneexchange
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/base58.py to base58.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/memo.py to memo.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/transactions.py to transactions.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/account.py to account.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/dictionary.py to dictionary.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/bip38.py to bip38.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/graphenebase/__init__.py to __init__.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneextra/proposal.py to proposal.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneextra/__init__.py to __init__.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/graphenewsprotocol.py to graphenewsprotocol.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/graphenewsrpc.py to graphenewsrpc.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/grapheneclient.py to grapheneclient.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/grapheneapi.py to grapheneapi.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/graphenews.py to graphenews.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneapi/__init__.py to __init__.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneexchange/exchange.py to exchange.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneexchange/grapheneexchange.py to grapheneexchange.cpython-35.pyc
byte-compiling build/bdist.linux-armv7l/egg/grapheneexchange/__init__.py to __init__.cpython-35.pyc
creating build/bdist.linux-armv7l/egg/EGG-INFO
copying graphenelib.egg-info/PKG-INFO -> build/bdist.linux-armv7l/egg/EGG-INFO
copying graphenelib.egg-info/SOURCES.txt -> build/bdist.linux-armv7l/egg/EGG-INFO
copying graphenelib.egg-info/dependency_links.txt -> build/bdist.linux-armv7l/egg/EGG-INFO
copying graphenelib.egg-info/top_level.txt -> build/bdist.linux-armv7l/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating 'dist/graphenelib-0.2rc5-py3.5.egg' and adding 'build/bdist.linux-armv7l/egg' to it
removing 'build/bdist.linux-armv7l/egg' (and everything under it)
Processing graphenelib-0.2rc5-py3.5.egg
Removing /home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg
Copying graphenelib-0.2rc5-py3.5.egg to /home/jason/.local/lib/python3.5/site-packages
graphenelib 0.2rc5 is already the active version in easy-install.pth

Installed /home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg
Processing dependencies for graphenelib==0.2rc5
Finished processing dependencies for graphenelib==0.2rc5
[jason@i4p python-graphenelib]$ pip install --user --upgrade -r requirements.txt graphenelib
Requirement already up-to-date: graphenelib in /home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg
Requirement already up-to-date: autobahn in /home/jason/.local/lib/python3.5/site-packages (from -r requirements.txt (line 1))
Requirement already up-to-date: requests in /home/jason/.local/lib/python3.5/site-packages (from -r requirements.txt (line 2))
Requirement already up-to-date: pycrypto in /usr/lib/python3.5/site-packages (from -r requirements.txt (line 3))
Requirement already up-to-date: scrypt in /home/jason/.local/lib/python3.5/site-packages (from -r requirements.txt (line 4))
Requirement already up-to-date: ecdsa in /home/jason/.local/lib/python3.5/site-packages (from -r requirements.txt (line 5))
Requirement already up-to-date: websocket-client in /home/jason/.local/lib/python3.5/site-packages (from -r requirements.txt (line 6))
Requirement already up-to-date: six>=1.9.0 in /usr/lib/python3.5/site-packages (from autobahn->-r requirements.txt (line 1))
Requirement already up-to-date: txaio>=2.2.0 in /home/jason/.local/lib/python3.5/site-packages (from autobahn->-r requirements.txt (line 1))


error on Archlinux and ArchlinuxARM:
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-simpleticker-stats/main.py
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-simpleticker-stats/main.py", line 1, in <module>
    from grapheneexchange import GrapheneExchange
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/__init__.py", line 2, in <module>
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/exchange.py", line 1, in <module>
ImportError: cannot import name 'GrapheneClient'
[jason@i4p python-graphenelib]$ python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 1, in <module>
    from grapheneexchange import GrapheneExchange
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/__init__.py", line 2, in <module>
  File "/home/jason/.local/lib/python3.5/site-packages/graphenelib-0.2rc5-py3.5.egg/grapheneexchange/exchange.py", line 1, in <module>
ImportError: cannot import name 'GrapheneClient'



feeds port Ubuntu
2812934ms th_a       main.cpp:169                  main                 ] wdata.ws_server: ws://localhost:8090
2813021ms th_a       main.cpp:174                  main                 ] wdata.ws_user:  wdata.ws_password: 
2813141ms th_a       main.cpp:240                  main                 ] Listening for incoming HTTP RPC requests on 127.0.0.1:8092


error on Ubuntu:
Successfully installed graphenelib requests six
Cleaning up...
:~/tmp/python-graphenelib$ python3 ~/tmp/python-graphenelib/scripts/exchange-simpleticker-stats/main.py
Traceback (most recent call last):
  File "tmp/python-graphenelib/scripts/exchange-simpleticker-stats/main.py", line 1, in <module>
    from grapheneexchange import GrapheneExchange
ImportError: No module named 'grapheneexchange'

roadscape

http://cryptofresh.com  |  witness: roadscape


xeroc

I am running archlinux as well ..

Try

  make install-user

In the library root dir ..

iHashFury

Quote from: xeroc on January 12, 2016, 06:32:38 PM
You need to upgrade the python-graphenelib library .. read the README.md

pip install --user --upgrade -r requirements.txt graphenelib ran without errors, also tried a fresh git clone.

Could it be a Archlinux specific issue as feeds are working fine. Will try on an Ubuntu server tomorrow.


xeroc


iHashFury

I would like to run this bot but I'm stuck on No module named 'grapheneexchange'

python3 ~/tmp/git/python-graphenelib/scripts/exchange-simpleticker-stats/main.py
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-simpleticker-stats/main.py", line 1, in <module>
    from grapheneexchange import GrapheneExchange
ImportError: No module named 'grapheneexchange'


python3 ~/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py
Traceback (most recent call last):
  File "/home/jason/tmp/git/python-graphenelib/scripts/exchange-bridge-market-maker/main.py", line 1, in <module>
    from grapheneexchange import GrapheneExchange
ImportError: No module named 'grapheneexchange'


Do I need to set parameters in  python-graphenelib/grapheneexchange/grapheneexchange.py ?

ebit

telegram:ebit521
[url="https://weibo.com/ebiter"]https://weibo.com/ebiter[/url]

kuro112

hey this is awesome, i dabble in python myself but this blows me away.

nice job.
CTO @ Freebie, LLC

xeroc

I just fixed some bugs in the "sell" and "buy" methods .. It is important for the bot developer to understand that prices should always be denoted in 'quote'.
For example: in the USD_BTS market .. a price of 0.5 means ... every 1 BTS costs 0.5 USD.

Further .. I implemented a POC for a bot that places orders around the peg in markets that are supposed to trade near 1 (BTC:OPENBTC, etc...)
The script can be found here:
https://github.com/xeroc/python-graphenelib/blob/master/scripts/exchange-bridge-market-maker
Documentation is here:
http://python-graphenelib.readthedocs.org/en/latest/scripts-exchange-bridge-market-maker.html

I hope to see alot tighter pegs in some of these markets ..


abit

BitShares committee member: abit
BitShares witness: in.abit

cass

█║▌║║█  - - -  The quieter you become, the more you are able to hear  - - -  █║▌║║█

Riverhead



I can verify that the exchange-simpleticker-stats example works on a clean 14.04 install :D.


Great work Xeroc!


BunkerChainLabs-DataSecurityNode

+-+-+-+-+-+-+-+-+-+-+
[url="//www.peerplays.com"]www.Peerplays.com[/url] | Decentralized Gaming Built with Graphene - Now with BookiePro and Sweeps!
+-+-+-+-+-+-+-+-+-+-+

xeroc

I present to you a *release candidate* for a python module that can be
used to easily build a trading bot.

As an orientation, I used the polonex trading interface. However there
are some differences that you should be aware of:

* market pairs are denoted as 'quote'_'base', e.g. `USD_BTS`
* Prices/Rates are denoted in 'quote', i.e. the USD_BTS market
   is priced in USD and buying 1 USD costs `rate` BTS
* All markets could be considered reversed as well ('BTS_USD')

Usage
... is quite simple:


dex = GrapheneExchange(config)
dex.returnTradeHistory("USD_BTS")
dex.returnTicker()
dex.return24Volume()
dex.returnOrderBook("USD_BTS")
dex.returnBalances()
dex.returnOpenOrders("all")
dex.buy("USD_BTS", 0.001, 10)
dex.sell("USD_BTS", 0.001, 10)


Documentation:
http://python-graphenelib.readthedocs.org/en/latest/exchange.html

Example Usage:
Script: https://github.com/xeroc/python-graphenelib/blob/master/scripts/exchange-simpleticker-stats/main.py
Output:

CNY_BTS
=======
- Trade Premium: 8.109%
- Bid Order Premium: 1.171%
- Ask Order Premium: 8.109%
- Spread: 6.630%
- CER premium:  5.22%

GOLD_BTS
========
- Trade Premium: 2.264%
- Bid Order Premium: 19.559%
- Ask Order Premium: 2.264%
- Spread: 19.413%
- CER premium:  3.53%

USD_BTS
=======
- Trade Premium: 0.180%
- Bid Order Premium: 2.137%
- Ask Order Premium: 0.439%
- Spread: 1.721%
- CER premium:  4.97%

SILVER_BTS
==========
- Trade Premium: 8.595%
- Bid Order Premium: 8.098%
- Ask Order Premium: 1.031%
- Spread: 9.464%
- CER premium:  4.16%


So,

To all the Traders and Bot developers:
* Please give this library a try and improve liquidity in the markets
* Note that the library is not well tested yet, so please a) use only
  what you can affort to lose and b) review the code :)


cass edit: title spelling mistake  GrapehenExchange  --> GrapheneExchange