Author Topic: Wrapper for Common PyBitshares DEX Algo Trading API Calls  (Read 4589 times)

0 Members and 1 Guest are viewing this topic.

Offline litepresence

'''CANCEL ALL VERSION 2'''        h/t @juhni

this version cancels all with a single API call using a list of string ID's

the method is not documented here:

http://docs.pybitshares.com/en/latest/market.html

says:

Quote
cancel(orderNumber, account=None)
Cancels an order you have placed in a given market. Requires only the “orderNumber”. An order number takes the form 1.7.xxx.

Parameters:   orderNumber (str) – The Order Object ide of the form 1.7.xxxx

apparently we can also use a list of str

Code: [Select]
    if command == 'cancel':

        # cancel all orders in this MARKET relentlessly until satisfied
        print(('Bitshares API', command)) 
        orders = MARKET.accountopenorders()
        print((len(orders), 'open orders to cancel'))
        if len(orders):
            attempt = 1   
            order_list = []     
            for order in orders:
                order_list.append(order['id'])
            while attempt:
                try:
                    details = MARKET.cancel(order_list)
                    print (details)
                    attempt = 0
                except:
                    print((attempt, 'cancel failed', order_list))
                    attempt += 1
                    if attempt > 10:
                        print ('cancel aborted')
                        return
                    pass

Offline litepresence

Quote
3 issue still working on
[/quote

I seem to have resolved this as well.

I was calling on 'BTC' markets I needed to be calling 'OPEN.BTC'


Offline litepresence

Quote
the block number updates but is 10 blocks slow
relative to my open gui wallet that is counting blocks upward and connected

the blocktimestamp updates but is 5 hours too fast
relative to time.time()

the price data / book is not updating and is stale/not correct at the onset
relative to the price data I see in my gui bitshares exchange

so issue one was resolved using

Code: [Select]
    CHAIN =  Blockchain(bitshares_instance=BitShares(
        nodes()),mode='head')

mode='head' means latest block even if not irreversible

second issue I created another thread for... it seems to be a bug related to timezone

3 issue still working on

Offline litepresence

This looks great!

Just a matter of time until soneone sets up a bot that does sophisticated orders like stop-loss etc ...

indeed

https://imgur.com/b694qzs.png

Offline litepresence

I pulled this list off the gui wallet:

Code: [Select]
nodes = [   
            'wss://bit.btsabc.org/ws',
            'wss://eu.openledger.info/ws',
            'wss://dexnode.net/ws',
            'wss://ws.gdex.top',
            'wss://kc-us-dex.xeldal.com/ws',
            'wss://bts.ai.la/ws',
            'wss://btsza.co.za:8091/ws',
            'wss://japan.bitshares.apasia.tech/ws',
            'wss://api.bts.blckchnd.com',
            'wss://bitshares-api.wancloud.io/ws',
            'wss://eu.nodes.bitshares.ws',
            'wss://bitshares.crypto.fans/ws',
            'wss://dex.rnglab.org',
            'wss://bitshares.openledger.info/ws',
            'wss://ws.winex.pro',
            'wss://sg.nodes.bitshares.ws',
            'wss://us.nodes.bitshares.ws',
            'wss://bitshares.apasia.tech/ws',
            'wss://openledger.hk/ws',
            'wss://bitshares.dacplay.org/ws',
            'wss://bitshares.openledger.info/ws',
            'wss://bitshares.dacplay.org:8089/ws',
            'wss://dele-puppy.com/ws',
            'wss://eu.openledger.info/ws',
        ]


surely there's better way than copy paste from gui and strip text for starting with wss ??  some api to call?
« Last Edit: February 25, 2018, 06:21:03 pm by litepresence »

Offline litepresence

Quote
list OF API NODES
Quote
is there api way to fetch this list, else what is best source?

I found this and it works in the format you suggested, but does not solve the issues in previous post

Code: [Select]
nodes = ['wss://bitshares.openledger.info/ws',
                'wss://bitshares.dacplay.org:8089/ws',
                'wss://dele-puppy.com/ws']

from docs here:

http://docs.bitshares.org/integration/traders/


is there a dynamically updated list or is that fairly static and reliable?
« Last Edit: February 25, 2018, 05:52:43 pm by litepresence »

Offline litepresence

Quote
list OF API NODES

is there api way to fetch this list, else what is best source?

also experiencing some issues:

I run this:

Code: [Select]
from bitshares.blockchain import Blockchain

now = time.time()
chain = Blockchain()
current_block = chain.get_current_block_num()
blocktime = chain.block_time(current_block)
blocktimestamp = chain.block_timestamp(current_block)
print ('block           :', current_block)
print ('blocktime       :', blocktime)
print ('stamp           :', blocktimestamp)
print ('ctime(stamp)    :', time.ctime(blocktimestamp))
print ('now             :', now)
print ('ctime(now)      :', time.ctime(now))
drift = now - blocktimestamp
drifthours = drift/3600
print ('drift seconds   :', ('%.2f' % drift))
print ('drift hours     :', ('%.2f' % drifthours))

and this:

   

Code: [Select]
dex('last')
dex('account_value')



I get:


Code: [Select]
block           : 24736857
blocktime       : 2018-02-25 15:48:24
stamp           : 1519591704
ctime(stamp)    : Sun Feb 25 15:48:24 2018
now             : 1519573746.9503589
ctime(now)      : Sun Feb 25 10:49:06 2018
drift seconds   : -17957.05
drift hours     : -4.99
('Bitshares API', 'last', 'BTS:BTC')
{'highestBid': 0.0000188272226 BTC/BTS, 'lowestAsk': 0.0000192294582 BTC/BTS, 'latest': 0.0000192296154 BTC/BTS, 'core_exchange_rate': 1.0000000000 BTS/BTS, 'quoteVolume': 1,604.15817 BTS, 'percentChange': 5.28284118389577, 'baseVolume': 0.03025533 BTC, 'baseSettlement_price': 0.0000224399912 BTC/BTS}
0.00001923
('Bitshares API', 'book', 'BTS:BTC')
{'askv': [119.82921], 'askp': [1.9229451650394755e-05], 'bidv': [0.92791], 'bidp': [1.88272569537994e-05]}

the block number updates but is 10 blocks slow
relative to my open gui wallet that is counting blocks upward and connected

the blocktimestamp updates but is 5 hours too fast
relative to time.time()

the price data / book is not updating and is stale/not correct at the onset
relative to the price data I see in my gui bitshares exchange



????


buy/sell/cancel from dex() are working; live tested without issues
« Last Edit: February 25, 2018, 07:54:35 pm by litepresence »

Offline xeroc

  • Board Moderator
  • Hero Member
  • *****
  • Posts: 12920
  • ChainSquad GmbH
    • View Profile
    • ChainSquad GmbH
  • BitShares: xeroc
  • GitHub: xeroc
that just went over my head

rewind pls


what is Bitshares() vs Notify() and which did I use?
You probably use BitShares() somewhere if you dont know about Notify() :)

With Market(), you made use of BitShares() instanced internally.
Try something like this:

from bitshares import BitShares
bts = BitShares([list OF API NODES])
m = Market('USD:BTS", bitshares_instance=bts)
[/list]
« Last Edit: February 25, 2018, 11:52:05 am by xeroc »

Offline litepresence

that just went over my head

rewind pls


what is Bitshares() vs Notify() and which did I use?

Offline xeroc

  • Board Moderator
  • Hero Member
  • *****
  • Posts: 12920
  • ChainSquad GmbH
    • View Profile
    • ChainSquad GmbH
  • BitShares: xeroc
  • GitHub: xeroc
Assuming you use the BitShares() class, you can throw a list of endpoints at it and it will cycle thru them on connection issues.

If you are using Notify() class, however, I fear that cycling is not available there, due to websocket notification having been lost during reconnections

Offline litepresence

Code: [Select]
    if command == 'account_value':

        # returns estimated account value in BTS, BTC, USD
        print(('Bitshares API', command))
        raw = list(ACCOUNT.balances)
        balances = {}
        for i in range(len(raw)):
            balances[raw[i]['symbol']] = float(raw[i]['amount'])
        btc_value = 0
        for asset, amount in balances.items():
            market_pair = 'BTC:' + asset
            market = Market(market_pair)
            price = float(market.ticker()['latest'])
            value = amount/price
            if asset != 'USD':
                price = 1/price
            print (('%.4f' % value), 'BTC', ('%.2f' % amount),
                    asset, '@', ('%.8f' % price))
            btc_value+=value

        market_pair = 'BTC:USD'
        market = Market(market_pair)
        price = float(market.ticker()['latest'])
        usd_value = btc_value*price
        market_pair = 'BTC:BTS'
        market = Market(market_pair)
        price = float(market.ticker()['latest'])
        bts_value = btc_value*price
       
        print(  ('%.2f' % bts_value), 'BTS',
                ('%.4f' % btc_value), 'BTC',
                ('%.2f' % usd_value), 'USD')
        return bts_value, btc_value, usd_value

Offline Bangzi

  • Sr. Member
  • ****
  • Posts: 321
    • View Profile
    • Steemit: Bangzi
  • BitShares: bangzi
Just a matter of time until soneone sets up a bot that does sophisticated orders like stop-loss etc ...

A quick win could be to add support of Bitshares DEX to this: https://github.com/DeviaVir/zenbot ...

Good if can bring more market makers to Bitshares but they need to setup a node for stable connection.
Bitshares DEX - Over 1000 Coins, Buy, Sell, Transfer & List Any Coins |Free Signup Today: https://wallet.bitshares.org/?r=bangzi

Offline zapata42

  • Full Member
  • ***
  • Posts: 62
    • View Profile
  • BitShares: zapata42
Just a matter of time until soneone sets up a bot that does sophisticated orders like stop-loss etc ...

A quick win could be to add support of Bitshares DEX to this: https://github.com/DeviaVir/zenbot ...

Offline xeroc

  • Board Moderator
  • Hero Member
  • *****
  • Posts: 12920
  • ChainSquad GmbH
    • View Profile
    • ChainSquad GmbH
  • BitShares: xeroc
  • GitHub: xeroc
This looks great!

Just a matter of time until soneone sets up a bot that does sophisticated orders like stop-loss etc ...

Offline litepresence

v1 : https://pastebin.com/9zAbqx2A

updated Mar6/2018

v2 https://pastebin.com/pBzi8a4N

 - improved cancel all
 - block number / latency
 - account value in BTS, BTC, USD terms



license: WFTPLv2 http://www.wtfpl.net/about/
Code: [Select]
# python3.4
 
' Wrapper for Common PyBitshares DEX Algo Trading API Calls '
 
# data is in easy to quant float / list of floats / dict of floats format
 
    # buy / sell / cancel
    # outstanding orders
    # account balance for pair
    # complete account balance
    # orderbook
    # last_price
    # account value
    # latency
 
# if no price / amount specified executes market order buy/sell
# if no expiration specified default is 3.2 years
# cancels all outstanding orders in market
 
' BTS: litepresence1 '
 
# http://docs.pybitshares.com
from bitshares.market import Market
from bitshares.account import Account
from bitshares import BitShares
from bitshares.blockchain import Blockchain
import time
 
 
ACCOUNT = Account("")
PASS_PHRASE = ""
 
BitCURRENCY = 'OPEN.BTC'
BitASSET = 'BTS'
BitPAIR = BitASSET + ":" + BitCURRENCY
MARKET = Market(BitPAIR, bitshares_instance=BitShares(nodes()))
CHAIN = Blockchain(bitshares_instance=BitShares(
    nodes()), mode='head')
 
SATOSHI = 0.00000001
ANTISAT = 1 / SATOSHI
 
def nodes():  # Public Nodes List
 
    nodes = [
        'wss://b.mrx.im/ws',
        'wss://bitshares.openledger.info/ws',
        'wss://bitshares.dacplay.org:8089/ws',
        'wss://dele-puppy.com/ws',
        'wss://eu.openledger.info/ws',
        'wss://bit.btsabc.org/ws',
        'wss://eu.openledger.info/ws',
        'wss://dexnode.net/ws',
        'wss://ws.gdex.top',
        'wss://kc-us-dex.xeldal.com/ws',
        'wss://bts.ai.la/ws',
        'wss://btsza.co.za:8091/ws',
        'wss://japan.bitshares.apasia.tech/ws',
        'wss://api.bts.blckchnd.com',
        'wss://bitshares-api.wancloud.io/ws',
        'wss://eu.nodes.bitshares.ws',
        'wss://bitshares.crypto.fans/ws',
        'wss://dex.rnglab.org',
        'wss://bitshares.openledger.info/ws',
        'wss://ws.winex.pro',
        'wss://sg.nodes.bitshares.ws',
        'wss://us.nodes.bitshares.ws',
        'wss://bitshares.apasia.tech/ws',
        'wss://openledger.hk/ws',
        'wss://bitshares.dacplay.org/ws',
    ]
    return nodes
 
def dex(  # Public AND Private API Bitshares
        command, amount=ANTISAT, price=None,
        depth=1, expiration=ANTISAT):
 
    MARKET.bitshares.wallet.unlock(PASS_PHRASE)
    ACCOUNT.refresh()
 
    if command == 'buy':
 
        # buy relentlessly until satisfied or currency exhausted
        print(('Bitshares API', command))
        if price is None:
            price = ANTISAT
        print(('buying', amount, 'at', price))
        attempt = 1
        currency = float(ACCOUNT.balance(BitCURRENCY))
        if amount > 0.998 * currency * price:
            amount = 0.998 * currency * price
        if amount > 0:
            while attempt:
                try:
                    details = (MARKET.buy(price, amount, expiration))
                    print (details)
                    attempt = 0
                except:
                    print(("buy attempt %s failed" % attempt))
                    attempt += 1
                    if attempt > 10:
                        print ('buy aborted')
                        return
                    pass
        else:
            print('no currency to buy')
 
    if command == 'sell':
 
        # sell relentlessly until satisfied or assets exhausted
        expiration = 86400 * 7
        print(('Bitshares API', command))
        if price is None:
            price = SATOSHI
        print(('selling', amount, 'at', price))
        attempt = 1
        assets = float(ACCOUNT.balance(BitASSET))
        if amount > 0.998 * assets:
            amount = 0.998 * assets
        if amount > 0:
            while attempt:
                try:
                    details = (MARKET.sell(price, amount, expiration))
                    print (details)
                    attempt = 0
                except:
                    print(("sell attempt %s failed" % attempt))
                    attempt += 1
                    if attempt > 10:
                        print ('sell aborted')
                        return
                    pass
        else:
            print('no assets to sell')
 
    if command == 'cancel':
 
        # cancel all orders in this MARKET relentlessly until satisfied
        print(('Bitshares API', command)) 
        orders = MARKET.accountopenorders()
        print((len(orders), 'open orders to cancel'))
        if len(orders):
            attempt = 1 
            order_list = []     
            for order in orders:
                order_list.append(order['id'])
            while attempt:
                try:
                    details = MARKET.cancel(order_list)
                    print (details)
                    attempt = 0
                except:
                    print((attempt, 'cancel failed', order_list))
                    attempt += 1
                    if attempt > 10:
                        print ('cancel aborted')
                        return
                    pass   
 
    if command == 'orders':
 
        # dictionary of open orders in traditional format:
        # orderNumber, orderType, market, amount, price
        print(('Bitshares API', command))
        orders = []
        for order in MARKET.accountopenorders():
            orderNumber = order['id']
            asset = order['base']['symbol']
            currency = order['quote']['symbol']
            amount = float(order['base'])
            price = float(order['price'])
            orderType = 'buy'
            if asset == BitASSET:
                orderType = 'sell'
                price = 1 / price
            orders.append({'orderNumber': orderNumber,
                           'orderType': orderType,
                           'market': BitPAIR, 'amount': amount,
                           'price': price})
        for o in orders:
            print (o)
        if len(orders) == 0:
            print ('no open orders')
        return orders
 
    if command == 'market_balances':
 
        # dictionary of currency and assets in this MARKET
        print(('Bitshares API', command))
        currency = float(ACCOUNT.balance(BitCURRENCY))
        assets = float(ACCOUNT.balance(BitASSET))
        balances = {'currency': currency, 'assets': assets}
        print (balances)
        return balances
 
    if command == 'complete_balances':
 
        # dictionary of ALL account balances
        print(('Bitshares API', command))
        raw = list(ACCOUNT.balances)
        balances = {}
        for i in range(len(raw)):
            balances[raw[i]['symbol']] = float(raw[i]['amount'])
        print (balances)
        return balances
 
    if command == 'book':
 
        # dictionary of 4 lists containing bid/ask volume/price
        print(('Bitshares API', command))
        raw = MARKET.orderbook(limit=depth)
        bids = raw['bids']
        asks = raw['asks']
        bidp = [float(bids[i]['price']) for i in range(len(bids))]
        bidv = [float(bids[i]['quote']) for i in range(len(bids))]
        askp = [float(asks[i]['price']) for i in range(len(asks))]
        askv = [float(asks[i]['quote']) for i in range(len(asks))]
        book = {'bidp': bidp, 'bidv': bidv, 'askp': askp, 'askv': askv}
        # print(book)
        print(('ask', ('%.8f' % book['askp'][0])))  # lowest ask price
        print(('bid', ('%.8f' % book['bidp'][0])))  # highest bid price
        # print(book['bidv'][0]) #highest bid volume
        # print(book['askv'][0]) #lowest ask volume
        return book
 
    if command == 'last':
 
        # the most recent transation in this MARKET
        print(('Bitshares API', command))
        raw = MARKET.ticker()['latest']
        price = float(raw)
        # print (price)
        return price
 
    if command == 'account_value':
 
        # dictionary account value in BTS BTC and USD
        print(('Bitshares API', command))
        raw = list(ACCOUNT.balances)
        balances = {}
        for i in range(len(raw)):
            balances[raw[i]['symbol']] = float(raw[i]['amount'])
        btc_value = 0
        for asset, amount in list(balances.items()):
            market_pair = 'OPEN.BTC:' + asset
            market = Market(market_pair)
            price = float(market.ticker()['latest'])
            try:
                value = amount / price
            except:
                value = 0
            if value < 0.0001:
                value = 0
            else:
                if asset != 'USD':
                    price = 1 / (price + SATOSHI)
                print((('%.4f' % value), 'OPEN.BTC', ('%.2f' % amount),
                       asset, '@', ('%.8f' % price)))
                btc_value += value
 
        market_pair = 'OPEN.BTC:USD'
        market = Market(market_pair)
        price = float(market.ticker()['latest'])
        usd_value = btc_value * price
        market_pair = 'OPEN.BTC:BTS'
        market = Market(market_pair)
        price = float(market.ticker()['latest'])
        bts_value = btc_value * price
        print((('%.2f' % bts_value), 'BTS',
             ('%.4f' % btc_value), 'OPEN.BTC',
             ('%.2f' % usd_value), 'bitUSD'))
        return bts_value, btc_value, usd_value
 
    if command == 'blocktime':
 
        current_block = CHAIN.get_current_block_num()
        blocktime = CHAIN.block_time(current_block)
        blocktimestamp = CHAIN.block_timestamp(current_block) - 18000
        now = time.time()
        latency = now - blocktimestamp
        print(('block               :', current_block))
        # print(('blocktime           :', blocktime))
        # print(('stamp               :', blocktimestamp))
        # print(('ctime(stamp)        :', time.ctime(blocktimestamp)))
        # print(('now                 :', now))
        print(('dex_rate latency    :', ('%.2f' % latency)))
        return current_block, blocktimestamp, latency
 
 
 
'''
dex('buy')
dex('sell')
dex('orders')
dex('cancel')
dex('market_balances')
dex('complete_balances')
dex('last')
dex('book')
dex('account_value')
dex('blocktime')
'''
« Last Edit: March 06, 2018, 05:16:39 pm by litepresence »