BitShares Forum
Main => Technical Support => Topic started by: litepresence on February 22, 2018, 03:29:25 pm
-
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/
# 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')
'''
-
This looks great!
Just a matter of time until soneone sets up a bot that does sophisticated orders like stop-loss etc ...
-
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 ...
-
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.
-
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
-
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
-
that just went over my head
rewind pls
what is Bitshares() vs Notify() and which did I use?
-
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]
-
list OF API NODES
is there api way to fetch this list, else what is best source?
also experiencing some issues:
I run this:
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:
dex('last')
dex('account_value')
I get:
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
-
list OF API NODES
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
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?
-
I pulled this list off the gui wallet:
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?
-
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
-
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
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
-
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'
-
'''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:
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
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