Following current various discussions on price feeds I spend a couple of days tuning mine.
Here is the algorithm I use:
- Get BTC/USD, ETH/USD, USDT/USD from CoinMarketCap.com (fallback to worldcoinindex.com)
- Get Fiat forex USD/CNY, USD/EUR, ... from CurrencyLayer (fallback to OpenExchangeRates)
- Get BITCNY/CNY from MagicWallet (use last 1h data, and if not enough trades use last 24h data)
- Get last price and daily volume of BTS/USDT, BTS/BTC, BTS/ETH if available from Centralized Exchanges: Aex, Binance, CoinEgg, CoinTiger, Huobi, Lbank, Poloniex, Zb
- Get last price and daily volume from BTS/OPEN.BTC, BTS/GDEX.BTC on BitShares DEX (and consider xxx.BTC = BTC)
- Get last price for BITCNY/BTC, BITCNY/ETH from CoinTiger
- Get last price for BTS/BITCNY from BitShares DEX
With that I compute all possible routes using BTC, ETH, USDT or BITCNY as intermediate asset.
Then I use a weighted average using the BTS/{BTC,ETH,USDT,BITCNY} daily volume.
Here is a sample result of all the routes for USD/BTS and CNY/BTS at 17/08/2018 21:58 UTC:
+------+-------+--------------+-------+--------------------+------------------------------------------------------------------------------------+
| base | quote | price | diff | quote volume | source |
+------+-------+--------------+-------+--------------------+------------------------------------------------------------------------------------+
| CNY | BTS | 0.8008708826 | +1.58 | 31726149.140697803 | ['magicwallet - CNY:BITCNY', 'bitshares - BITCNY:BTS'] |
| CNY | BTS | 0.7775048363 | -1.38 | 275814.57983 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'gdex - BTC:BTS'] |
| CNY | BTS | 0.7767051983 | -1.48 | 6099695.41644055 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'poloniex - BTC:BTS'] |
| CNY | BTS | 0.7776046832 | -1.37 | 6823092.1 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'zb - BTC:BTS'] |
| CNY | BTS | 0.7826822718 | -0.73 | 1944911.60043 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'openledger - BTC:BTS'] |
| CNY | BTS | 0.7897477292 | +0.17 | 8090672.0 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'coinegg - BTC:BTS'] |
| CNY | BTS | 0.7821021076 | -0.80 | 719268.12 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'cointiger - BTC:BTS'] |
| CNY | BTS | 0.7758057134 | -1.60 | 3068685.9901371617 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'huobi - BTC:BTS'] |
| CNY | BTS | 0.7816523652 | -0.86 | 1648254.1922999984 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'lbank - BTC:BTS'] |
| CNY | BTS | 0.7798533954 | -1.08 | 5457868.0 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:BTC', 'binance - BTC:BTS'] |
| CNY | BTS | 0.7968423519 | +1.07 | 275814.57983 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'gdex - BTC:BTS'] |
| CNY | BTS | 0.7960228259 | +0.97 | 6099695.41644055 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'poloniex - BTC:BTS'] |
| CNY | BTS | 0.7969446821 | +1.08 | 6823092.1 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'zb - BTC:BTS'] |
| CNY | BTS | 0.8021485567 | +1.74 | 1944911.60043 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'openledger - BTC:BTS'] |
| CNY | BTS | 0.8093897408 | +2.66 | 8090672.0 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'coinegg - BTC:BTS'] |
| CNY | BTS | 0.8015539631 | +1.67 | 719268.12 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'cointiger - BTC:BTS'] |
| CNY | BTS | 0.7951009697 | +0.85 | 3068685.9901371617 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'huobi - BTC:BTS'] |
| CNY | BTS | 0.8010930350 | +1.61 | 1648254.1922999984 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'lbank - BTC:BTS'] |
| CNY | BTS | 0.7992493226 | +1.38 | 5457868.0 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:BTC', 'binance - BTC:BTS'] |
| CNY | BTS | 0.7739653886 | -1.83 | 17591765.91406 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:USDT', 'aex - USDT:BTS'] |
| CNY | BTS | 0.7767270849 | -1.48 | 15976040.0 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:USDT', 'zb - USDT:BTS'] |
| CNY | BTS | 0.7794887812 | -1.13 | 10213236.688898135 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:USDT', 'huobi - USDT:BTS'] |
| CNY | BTS | 0.7760030565 | -1.57 | 188647.0 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:ETH', 'cointiger - ETH:BTS'] |
| CNY | BTS | 0.7760030565 | -1.57 | 1040797.2504070019 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:ETH', 'huobi - ETH:BTS'] |
| CNY | BTS | 0.7778900585 | -1.33 | 4698376.790000004 | ['openexchangerates - CNY:USD', 'coinmarketcap - USD:ETH', 'lbank - ETH:BTS'] |
| CNY | BTS | 0.7930701250 | +0.59 | 188647.0 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:ETH', 'cointiger - ETH:BTS'] |
| CNY | BTS | 0.7930701250 | +0.59 | 1040797.2504070019 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:ETH', 'huobi - ETH:BTS'] |
| CNY | BTS | 0.7949986288 | +0.84 | 4698376.790000004 | ['magicwallet - CNY:BITCNY', 'cointiger - BITCNY:ETH', 'lbank - ETH:BTS'] |
| USD | BTS | 0.1130179495 | -0.27 | 275814.57983 | ['coinmarketcap - USD:BTC', 'gdex - BTC:BTS'] |
| USD | BTS | 0.1129017143 | -0.37 | 6099695.41644055 | ['coinmarketcap - USD:BTC', 'poloniex - BTC:BTS'] |
| USD | BTS | 0.1130324632 | -0.26 | 6823092.1 | ['coinmarketcap - USD:BTC', 'zb - BTC:BTS'] |
| USD | BTS | 0.1137705405 | +0.39 | 1944911.60043 | ['coinmarketcap - USD:BTC', 'openledger - BTC:BTS'] |
| USD | BTS | 0.1147975740 | +1.30 | 8090672.0 | ['coinmarketcap - USD:BTC', 'coinegg - BTC:BTS'] |
| USD | BTS | 0.1136862080 | +0.32 | 719268.12 | ['coinmarketcap - USD:BTC', 'cointiger - BTC:BTS'] |
| USD | BTS | 0.1127709653 | -0.49 | 3068685.9901371617 | ['coinmarketcap - USD:BTC', 'huobi - BTC:BTS'] |
| USD | BTS | 0.1136208335 | +0.26 | 1648254.1922999984 | ['coinmarketcap - USD:BTC', 'lbank - BTC:BTS'] |
| USD | BTS | 0.1133593356 | +0.03 | 5457868.0 | ['coinmarketcap - USD:BTC', 'binance - BTC:BTS'] |
| USD | BTS | 0.1125034561 | -0.72 | 17591765.91406 | ['coinmarketcap - USD:USDT', 'aex - USDT:BTS'] |
| USD | BTS | 0.1129048957 | -0.37 | 15976040.0 | ['coinmarketcap - USD:USDT', 'zb - USDT:BTS'] |
| USD | BTS | 0.1133063354 | -0.02 | 10213236.688898135 | ['coinmarketcap - USD:USDT', 'huobi - USDT:BTS'] |
| USD | BTS | 0.1127996511 | -0.46 | 188647.0 | ['coinmarketcap - USD:ETH', 'cointiger - ETH:BTS'] |
| USD | BTS | 0.1127996511 | -0.46 | 1040797.2504070019 | ['coinmarketcap - USD:ETH', 'huobi - ETH:BTS'] |
| USD | BTS | 0.1130739453 | -0.22 | 4698376.790000004 | ['coinmarketcap - USD:ETH', 'lbank - ETH:BTS'] |
| USD | BTS | 0.1128235134 | -0.44 | 275814.57983 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'gdex - BTC:BTS'] |
| USD | BTS | 0.1127074782 | -0.54 | 6099695.41644055 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'poloniex - BTC:BTS'] |
| USD | BTS | 0.1128380022 | -0.43 | 6823092.1 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'zb - BTC:BTS'] |
| USD | BTS | 0.1135748097 | +0.22 | 1944911.60043 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'openledger - BTC:BTS'] |
| USD | BTS | 0.1146000762 | +1.13 | 8090672.0 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'coinegg - BTC:BTS'] |
| USD | BTS | 0.1134906222 | +0.15 | 719268.12 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'cointiger - BTC:BTS'] |
| USD | BTS | 0.1125769542 | -0.66 | 3068685.9901371617 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'huobi - BTC:BTS'] |
| USD | BTS | 0.1134253602 | +0.09 | 1648254.1922999984 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'lbank - BTC:BTS'] |
| USD | BTS | 0.1131643122 | -0.14 | 5457868.0 | ['coinmarketcap - USD:USDT', 'coinmarketcap - USDT:BTC', 'binance - BTC:BTS'] |
| USD | BTS | 0.1128514039 | -0.42 | 275814.57983 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'gdex - BTC:BTS'] |
| USD | BTS | 0.1127353400 | -0.52 | 6099695.41644055 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'poloniex - BTC:BTS'] |
| USD | BTS | 0.1128658963 | -0.40 | 6823092.1 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'zb - BTC:BTS'] |
| USD | BTS | 0.1136028859 | +0.25 | 1944911.60043 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'openledger - BTC:BTS'] |
| USD | BTS | 0.1146284059 | +1.15 | 8090672.0 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'coinegg - BTC:BTS'] |
| USD | BTS | 0.1135186776 | +0.17 | 719268.12 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'cointiger - BTC:BTS'] |
| USD | BTS | 0.1126047837 | -0.63 | 3068685.9901371617 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'huobi - BTC:BTS'] |
| USD | BTS | 0.1134533995 | +0.11 | 1648254.1922999984 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'lbank - BTC:BTS'] |
| USD | BTS | 0.1131922869 | -0.12 | 5457868.0 | ['coinmarketcap - USD:ETH', 'coinmarketcap - ETH:BTC', 'binance - BTC:BTS'] |
| USD | BTS | 0.1126973406 | -0.55 | 17591765.91406 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:USDT', 'aex - USDT:BTS'] |
| USD | BTS | 0.1130994721 | -0.20 | 15976040.0 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:USDT', 'zb - USDT:BTS'] |
| USD | BTS | 0.1135016035 | +0.16 | 10213236.688898135 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:USDT', 'huobi - USDT:BTS'] |
| USD | BTS | 0.1135893251 | +0.23 | 31726149.140697803 | ['coinmarketcap - USD:BTC', 'cointiger - BTC:BITCNY', 'bitshares - BITCNY:BTS'] |
| USD | BTS | 0.1139091655 | +0.52 | 31726149.140697803 | ['coinmarketcap - USD:ETH', 'cointiger - ETH:BITCNY', 'bitshares - BITCNY:BTS'] |
| USD | BTS | 0.1129661203 | -0.32 | 188647.0 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:ETH', 'cointiger - ETH:BTS'] |
| USD | BTS | 0.1129661203 | -0.32 | 1040797.2504070019 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:ETH', 'huobi - ETH:BTS'] |
| USD | BTS | 0.1132408193 | -0.07 | 4698376.790000004 | ['coinmarketcap - USD:BTC', 'coinmarketcap - BTC:ETH', 'lbank - ETH:BTS'] |
+------+-------+--------------+-------+--------------------+------------------------------------------------------------------------------------+
And the final results I get:
+--------+------------+--------------+--------------+---------------------+---------------------+---------------------+--------------+---------------------+--------+--------+-------------------------+-------------+
| symbol | collateral | new price | cer | mean | median | wgt. avg. | wgt. std (#) | blockchain | mssr | mcr | my last price | last update |
+--------+------------+--------------+--------------+---------------------+---------------------+---------------------+--------------+---------------------+--------+--------+-------------------------+-------------+
| CNY | BTS | 0.7884066494 | 0.9460879792 | 0.7880032477 (0.05) | 0.7862150005 (0.28) | 0.7884066494 (0.00) | 1.17 (28) | 0.7728333333 (2.02) | 110.0% | 175.0% | -1.0000000000 (-178.84) | unknown ago |
| USD | BTS | 0.1133240311 | 0.1189902327 | 0.1132431633 (0.07) | 0.1130994721 (0.20) | 0.1133240311 (0.00) | 0.06 (41) | 0.1123699660 (0.85) | 110.0% | 175.0% | -1.0000000000 (-111.33) | unknown ago |
+--------+------------+--------------+--------------+---------------------+---------------------+---------------------+--------------+---------------------+--------+--------+-------------------------+-------------+
I use xeroc's pricefeed script that I modified again to add:
- Composite source to group multiple sources as one (to handle things like fallbacks);
- Add CoinTiger, CoinEgg, Huobi and MagicWallet sources;
- Change the way derived routes volumes are computed;
- Better tracking of source for debug/audit purpose;
- Various code refactoring and small enhancements.
All code is accessible at
Zapata/bitshares-pricefeed.
Your comments are more than welcome, this is intended to be adjusted over time.
Currently my ideas to further improve are:
- use the volume weighted average of the last X minutes trades instead of the last prices.
- use the order book depth to weight prices instead of daily volume.
- plot and track current active feeds and backup/test feeds over time. This will help shareholders to vote accurately.
- make all the data used for all my feeds publicly available for auditing
I would be able to progress on that once voted. Since then I'm helping Alfredo on the open-explorer (see
last PR).