'),h&&a(".sticky-queue").prepend(j.replace("POS",f.position).replace("ID",g).replace("NOTE",b).replace("CLASSLIST",f.classList)).find("#"+g).slideDown(f.speed,function(){h=!0,d&&"function"==typeof d&&d({id:g,duplicate:i,displayed:h})}),a(".sticky").ready(function(){f.autoclose&&a("#"+g).delay(f.autoclose).fadeOut(f.speed,function(){a(this).remove()})}),a(".sticky-close").on("click",function(){a("#"+a(this).parent().attr("id")).dequeue().fadeOut(f.speed,function(){a(this).remove()})})}}(jQuery);
--------------------------------------------------------------------------------
/static/surbitcoin_maintenance.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Estamos realizando operaciones de mantenimiento. Disculpen las molestias.
79 | Estaremos de vuelta en una hora
80 |
81 |
82 |
83 |
84 |
85 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/static/surbitcoin_tos.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blinktrade/bitex/a4896e7faef9c4aa0ca5325f18b77db67003764e/static/surbitcoin_tos.html
--------------------------------------------------------------------------------
/tools/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'rodrigo'
2 |
--------------------------------------------------------------------------------
/tools/arbitrage/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blinktrade/bitex/a4896e7faef9c4aa0ca5325f18b77db67003764e/tools/arbitrage/__init__.py
--------------------------------------------------------------------------------
/tools/arbitrage/arbitrage.ini:
--------------------------------------------------------------------------------
1 | [bitstamp1]
2 | websocket_url= wss://api.testnet.blinktrade.com/trade/
3 | username = user
4 | password = abc12345
5 | buy_fee = 0
6 | sell_fee = 0
7 | broker_id=5
8 | dest_market=BTCUSD
9 |
10 | [bitstamp]
11 | websocket_url= wss://api.testnet.blinktrade.com/trade/
12 | username = user
13 | password = abc12345
14 | buy_fee = -2.00
15 | sell_fee = 2.00
16 | broker_id=5
17 | dest_market=BTCUSD
18 |
19 |
20 | [b2u]
21 | websocket_url= wss://api.testnet.blinktrade.com/trade/
22 | broker_id=5
23 | username = user
24 | password = abc12345
25 | buy_fee = 0
26 | sell_fee = 0
27 | broker_id=5
28 | dest_market=BTCUSD
29 |
30 |
31 | [basebit]
32 | websocket_url= wss://api.testnet.blinktrade.com/trade/
33 | username = user
34 | password = abc12345
35 | buy_fee = 0
36 | sell_fee = 0
37 | broker_id=5
38 | dest_market=BTCUSD
39 |
40 |
41 | [bitfinex]
42 | websocket_url= wss://api.testnet.blinktrade.com/trade/
43 | username = user
44 | password = abc12345
45 | buy_fee = 0
46 | sell_fee = 0
47 | broker_id=5
48 | dest_market=BTCUSD
49 |
50 |
51 | [bitinvest]
52 | websocket_url= wss://api.testnet.blinktrade.com/trade/
53 | username = user
54 | password = abc12345
55 | buy_fee = 0
56 | sell_fee = 0
57 | subscription_api_key = fc848c1b8ead44bc99db3a80f7dfb882
58 | broker_id=5
59 | dest_market=BTCUSD
60 |
61 |
62 | [hitbtc]
63 | websocket_url= wss://api.testnet.blinktrade.com/trade/
64 | username = user
65 | password = abc12345
66 | buy_fee = 0
67 | sell_fee = 0
68 | broker_id=5
69 | dest_market=BTCUSD
70 |
71 | [itbit1]
72 | websocket_url= wss://api.testnet.blinktrade.com/trade/
73 | username = user
74 | password = abc12345
75 | buy_fee = 0
76 | sell_fee = 0
77 | broker_id=5
78 | dest_market=BTCUSD
79 |
80 | [mb]
81 | websocket_url= wss://api.testnet.blinktrade.com/trade/
82 | username = user
83 | password = abc12345
84 | buy_fee = 0
85 | sell_fee = 0
86 | broker_id=5
87 | dest_market=BTCUSD
88 |
89 |
--------------------------------------------------------------------------------
/tools/arbitrage/b2u.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 |
16 | B2U_API_KEY = 'XXXX'
17 | B2U_API_SECRET = 'YYYY'
18 |
19 | def send_order_to_b2u(sender, order):
20 | nonce = datetime.datetime.now().strftime('%s')
21 | message = str(nonce) + '.blinktrade.' + str(B2U_API_KEY)
22 | signature = hmac.new(B2U_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
23 |
24 | post_params = {
25 | 'key': B2U_API_KEY,
26 | 'signature': signature,
27 | 'nonce': nonce,
28 | 'amount': float(order['OrderQty']/1.e8),
29 | 'price': float(order['Price'] / 1.e8)
30 | }
31 |
32 | if msg['Side'] == '1':
33 | print datetime.datetime.now(), 'POST https://www.bitcointoyou.com/api/buy/', str(post_params)
34 | elif msg['Side'] == '2':
35 | print datetime.datetime.now(), 'POST https://www.bitcointoyou.com/api/sell/', str(post_params)
36 |
37 |
38 | def main():
39 | candidates = ['arbitrage.ini', 'b2u.ini' ]
40 | if len(sys.argv) > 1:
41 | candidates.append(sys.argv[1])
42 |
43 |
44 | config = ConfigParser.SafeConfigParser({
45 | 'websocket_url': 'wss://127.0.0.1/trade/',
46 | 'username': '',
47 | 'password': '',
48 | 'broker_id': 5,
49 | 'buy_fee': 0,
50 | 'sell_fee': 0,
51 | 'api_key': 'KEY',
52 | 'api_secret': 'SECRET'
53 | })
54 | config.read( candidates )
55 |
56 | websocket_url = config.get('b2u', 'websocket_url')
57 | username = config.get('b2u', 'username')
58 | password = config.get('b2u', 'password')
59 | buy_fee = int(config.get('b2u', 'buy_fee'))
60 | sell_fee = int(config.get('b2u', 'sell_fee'))
61 | api_key = config.get('b2u', 'api_key')
62 | api_secret = config.get('b2u', 'api_secret')
63 | broker_id = config.getint('b2u', 'broker_id')
64 | dest_market = config.get('b2u', 'dest_market')
65 |
66 | print 'websocket_url:', websocket_url
67 | print 'username:', username
68 | print 'buy_fee:', buy_fee
69 | print 'sell_fee:', sell_fee
70 |
71 | arbitrator = BlinkTradeArbitrator( broker_id, username,password,websocket_url, dest_market)
72 | arbitrator.connect()
73 |
74 | arbitrator.signal_order.connect(send_order_to_b2u)
75 |
76 | while True:
77 | try:
78 | sleep(10)
79 | if arbitrator.is_connected():
80 | arbitrator.send_testRequest()
81 | else:
82 | try:
83 | arbitrator.reconnect()
84 | except HandshakeError,e:
85 | continue
86 |
87 | try:
88 | raw_data = urllib2.urlopen('http://www.bitcointoyou.com/API/orderbook.aspx').read()
89 | except Exception:
90 | print 'ERROR RETRIEVING ORDER BOOK'
91 | continue
92 |
93 |
94 | bids_asks = []
95 | try:
96 | bids_asks = json.loads(raw_data)
97 | except Exception :
98 | try:
99 | bids_asks = json.loads(raw_data.replace('][','],[')) # bug with b2u api
100 | except Exception :
101 | pass
102 | pass
103 |
104 | if bids_asks:
105 | ask_list = [ [ int(float(fiat)*1e8 * (1. + sell_fee) ), int(float(btc) * 1e8) ] for fiat,btc in bids_asks['asks'] ]
106 | bid_list = [ [ int(float(fiat)*1e8 * (1. - buy_fee) ), int(float(btc) * 1e8) ] for fiat,btc in bids_asks['bids'] ]
107 |
108 | number_of_asks_to_remove_due_a_weird_bug = 0
109 | for ask_price, ask_size in ask_list:
110 | if ask_price < bid_list[0][0]:
111 | number_of_asks_to_remove_due_a_weird_bug += 1
112 | else:
113 | break
114 | if number_of_asks_to_remove_due_a_weird_bug:
115 | print datetime.datetime.now(), 'Those sell orders are weird => ', [ 'BTC {:,.8f}'.format(s/1e8) + ' @ R$ {:,.2f}'.format(p/1e8) for p, s in ask_list[:number_of_asks_to_remove_due_a_weird_bug] ]
116 |
117 | ask_list = ask_list[number_of_asks_to_remove_due_a_weird_bug:]
118 |
119 | arbitrator.process_ask_list(ask_list)
120 | arbitrator.process_bid_list(bid_list)
121 |
122 | except urllib2.URLError as e:
123 | print datetime.datetime.now(), e
124 |
125 | except KeyboardInterrupt:
126 | arbitrator.cancel_all_orders()
127 | print 'wait....'
128 | sleep(5)
129 | arbitrator.close()
130 | break
131 |
132 | main()
133 |
134 |
--------------------------------------------------------------------------------
/tools/arbitrage/basebit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 |
16 | BASEBIT_API_KEY = 'XXXX'
17 | BASEBIT_API_SECRET = 'YYYY'
18 |
19 | def send_order_to_basebit(sender, order):
20 | nonce = datetime.datetime.now().strftime('%s')
21 | message = 'sendorder' + str(BASEBIT_API_KEY) + str(nonce)
22 | signature = hmac.new(BASEBIT_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
23 |
24 | post_params = {
25 | 'key': BASEBIT_API_KEY,
26 | 'sign': signature,
27 | 'pair': order['Symbol'],
28 | 'quantity': float(order['OrderQty']/1.e8),
29 | 'price': float( order['Price'] / 1.e8)
30 | }
31 |
32 | if msg['Side'] == '1':
33 | post_params['type'] = 'buy'
34 | elif msg['Side'] == '2':
35 | post_params['type'] = 'sell'
36 |
37 | print datetime.datetime.now(), 'POST https://www.basebit.com.br/secure/tapi/' + message, str(post_params)
38 |
39 | def main():
40 | candidates = ['arbitrage.ini', 'basebit.ini' ]
41 | if len(sys.argv) > 1:
42 | candidates.append(sys.argv[1])
43 |
44 |
45 | config = ConfigParser.SafeConfigParser({
46 | 'websocket_url': 'wss://127.0.0.1/trade/',
47 | 'username': '',
48 | 'password': '',
49 | 'buy_fee': 0,
50 | 'sell_fee': 0,
51 | 'api_key': 'KEY',
52 | 'api_secret': 'SECRET'
53 | })
54 | config.read( candidates )
55 |
56 | websocket_url = config.get('basebit', 'websocket_url')
57 | username = config.get('basebit', 'username')
58 | password = config.get('basebit', 'password')
59 | buy_fee = int(config.get('basebit', 'buy_fee'))
60 | sell_fee = int(config.get('basebit', 'sell_fee'))
61 | api_key = config.get('basebit', 'api_key')
62 | api_secret = config.get('basebit', 'api_secret')
63 | broker_id = config.getint('basebit', 'broker_id')
64 | dest_market = config.get('basebit', 'dest_market')
65 |
66 | print 'websocket_url:', websocket_url
67 | print 'username:', username
68 | print 'buy_fee:', buy_fee
69 | print 'sell_fee:', sell_fee
70 |
71 | arbitrator = BlinkTradeArbitrator(broker_id, username,password,websocket_url, dest_market )
72 | arbitrator.connect()
73 |
74 | arbitrator.signal_order.connect(send_order_to_basebit)
75 |
76 | while True:
77 | try:
78 | sleep(10)
79 |
80 | if arbitrator.is_connected():
81 | arbitrator.send_testRequest()
82 | else:
83 | try:
84 | arbitrator.reconnect()
85 | except HandshakeError,e:
86 | continue
87 |
88 | try:
89 | raw_data = urllib2.urlopen('http://www.basebit.com.br/book-BTC_BRL').read()
90 | except Exception:
91 | print 'ERROR RETRIEVING ORDER BOOK'
92 | continue
93 |
94 | bids_asks = []
95 | try:
96 | bids_asks = json.loads(raw_data)
97 | except Exception :
98 | pass
99 |
100 | if bids_asks:
101 | ask_list = [ [ int(float(o['price']) * 1e8 * (1. + sell_fee) ) , int(o['quantity'] * 1e8) ] for o in bids_asks['result']['asks'] ]
102 | bid_list = [ [ int(float(o['price']) * 1e8 * (1. + buy_fee) ) , int(o['quantity'] * 1e8) ] for o in bids_asks['result']['bids'] ]
103 | arbitrator.process_ask_list(ask_list)
104 | arbitrator.process_bid_list(bid_list)
105 | except urllib2.URLError as e:
106 | print datetime.datetime.now(), e
107 |
108 | except KeyboardInterrupt:
109 | arbitrator.cancel_all_orders()
110 | print 'wait....'
111 | sleep(5)
112 |
113 | arbitrator.close()
114 | break
115 |
116 | main()
117 |
118 |
--------------------------------------------------------------------------------
/tools/arbitrage/bitfinex.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 | BITFINEX_API_KEY = 'XXXX'
16 | BITFINEX_API_SECRET = 'YYYY'
17 |
18 | def send_order_to_bitfinex(sender, order):
19 | nonce = datetime.datetime.now().strftime('%s')
20 | message = 'sendorder' + str(BITFINEX_API_KEY) + str(nonce)
21 | signature = hmac.new(BITFINEX_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
22 |
23 | post_params = {
24 | 'key': BITFINEX_API_KEY,
25 | 'sign': signature,
26 | 'pair': 'btc_brl',
27 | 'volume': float(order['OrderQty']/1.e8),
28 | 'price': float( order['Price'] / 1.e8)
29 | }
30 |
31 | if order['Side'] == '1':
32 | post_params['type'] = 'buy'
33 | elif order['Side'] == '2':
34 | post_params['type'] = 'sell'
35 |
36 | print datetime.datetime.now(), 'POST https://api.bitfinex.com/v1/tapi/' + message, str(post_params)
37 |
38 | def main():
39 | candidates = ['arbitrage.ini', 'bitfinex.ini' ]
40 | if len(sys.argv) > 1:
41 | candidates.append(sys.argv[1])
42 |
43 |
44 | config = ConfigParser.SafeConfigParser({
45 | 'websocket_url': 'wss://127.0.0.1/trade/',
46 | 'username': '',
47 | 'password': '',
48 | 'buy_fee': 0,
49 | 'sell_fee': 0,
50 | 'api_key': 'KEY',
51 | 'api_secret': 'SECRET'
52 | })
53 | config.read( candidates )
54 |
55 | websocket_url = config.get('bitfinex', 'websocket_url')
56 | username = config.get('bitfinex', 'username')
57 | password = config.get('bitfinex', 'password')
58 | buy_fee = int(config.get('bitfinex', 'buy_fee'))
59 | sell_fee = int(config.get('bitfinex', 'sell_fee'))
60 | api_key = config.get('bitfinex', 'api_key')
61 | api_secret = config.get('bitfinex', 'api_secret')
62 | broker_id = config.getint('bitfinex', 'broker_id')
63 | dest_market = config.get('bitfinex', 'dest_market')
64 |
65 | arbitrator = BlinkTradeArbitrator(broker_id, username,password,websocket_url, dest_market)
66 | arbitrator.connect()
67 |
68 | arbitrator.signal_order.connect(send_order_to_bitfinex)
69 |
70 | while True:
71 | try:
72 | sleep(1)
73 |
74 | if arbitrator.is_connected():
75 | arbitrator.send_testRequest()
76 | else:
77 | try:
78 | arbitrator.reconnect()
79 | except HandshakeError,e:
80 | continue
81 |
82 | try:
83 | raw_data = urllib2.urlopen('https://api.bitfinex.com/v1/book/BTCUSD').read()
84 | except Exception:
85 | print 'ERROR RETRIEVING ORDER BOOK'
86 | continue
87 |
88 |
89 | bids_asks = []
90 | try:
91 | bids_asks = json.loads(raw_data)
92 | except Exception :
93 | pass
94 |
95 | if bids_asks:
96 | bid_list = [ [ int(float(o['price']) * 1e8 * (1. + buy_fee) ) , int( float(o['amount']) * 1e8) ] for o in bids_asks['bids'] ]
97 | ask_list = [ [ int(float(o['price']) * 1e8 * (1. + sell_fee) ) , int( float(o['amount']) * 1e8) ] for o in bids_asks['asks'] ]
98 | arbitrator.process_ask_list(ask_list)
99 | arbitrator.process_bid_list(bid_list)
100 | except urllib2.URLError as e:
101 | print datetime.datetime.now(), e
102 |
103 | except KeyboardInterrupt:
104 | arbitrator.cancel_all_orders()
105 | print 'wait....'
106 | sleep(5)
107 | arbitrator.close()
108 | break
109 |
110 | main()
111 |
112 |
--------------------------------------------------------------------------------
/tools/arbitrage/bitinvest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import subprocess
13 | import ConfigParser
14 | from ws4py.exc import HandshakeError
15 |
16 |
17 | BINVEST_API_KEY = 'XXXX'
18 | BINVEST_API_SECRET = 'YYYY'
19 |
20 | def send_order_to_BINVEST(sender, order):
21 | nonce = datetime.datetime.now().strftime('%s')
22 | message = 'sendorder' + str(BINVEST_API_KEY) + str(nonce)
23 | signature = hmac.new(BINVEST_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
24 |
25 | post_params = {
26 | 'key': BINVEST_API_KEY,
27 | 'sign': signature,
28 | 'pair': 'btc_brl',
29 | 'volume': float(order['OrderQty']/1.e8),
30 | 'price': float( order['Price'] / 1.e8)
31 | }
32 |
33 | if msg['Side'] == '1':
34 | post_params['type'] = 'buy'
35 | elif msg['Side'] == '2':
36 | post_params['type'] = 'sell'
37 |
38 | print datetime.datetime.now(), 'POST https://api.bitinvest.com.br/tapi/' + message, str(post_params)
39 |
40 | def main():
41 | candidates = ['arbitrage.ini', 'basebit.ini' ]
42 | if len(sys.argv) > 1:
43 | candidates.append(sys.argv[1])
44 |
45 |
46 | config = ConfigParser.SafeConfigParser({
47 | 'websocket_url': 'wss://127.0.0.1/trade/',
48 | 'username': '',
49 | 'password': '',
50 | 'buy_fee': 0,
51 | 'sell_fee': 0,
52 | 'api_key': 'KEY',
53 | 'api_secret': 'SECRET',
54 | 'subscription_api_key':'api_key'
55 | })
56 | config.read( candidates )
57 |
58 | websocket_url = config.get('bitinvest', 'websocket_url')
59 | username = config.get('bitinvest', 'username')
60 | password = config.get('bitinvest', 'password')
61 | buy_fee = int(config.get('bitinvest', 'buy_fee'))
62 | sell_fee = int(config.get('bitinvest', 'sell_fee'))
63 | api_key = config.get('bitinvest', 'api_key')
64 | api_secret = config.get('bitinvest', 'api_secret')
65 | subscription_api_key = config.get('bitinvest', 'subscription_api_key')
66 | broker_id = config.getint('bitinvest', 'broker_id')
67 | dest_market = config.get('bitinvest', 'dest_market')
68 |
69 |
70 | arbitrator = BlinkTradeArbitrator(broker_id, username,password,websocket_url, dest_market)
71 | arbitrator.connect()
72 |
73 | arbitrator.signal_order.connect(send_order_to_BINVEST)
74 |
75 | while True:
76 | try:
77 | sleep(15)
78 | if arbitrator.is_connected():
79 | arbitrator.send_testRequest()
80 | else:
81 | try:
82 | arbitrator.reconnect()
83 | except HandshakeError,e:
84 | continue
85 |
86 | try:
87 | # something wrong with urllib2 or bitinvest servers.
88 | #raw_data = urllib2.urlopen('https://api.bitinvest.com.br/exchange/orderbook?subscription-key=' + subscription_api_key).read()
89 |
90 | # curl works. I know, this is ugly, but it works
91 | api_url = 'https://api.bitinvest.com.br/exchange/orderbook?subscription-key=' + subscription_api_key
92 | raw_data = subprocess.check_output( ['curl', api_url ] )
93 | except Exception:
94 | print 'ERROR RETRIEVING ORDER BOOK'
95 | continue
96 |
97 | bids_asks = []
98 | try:
99 | bids_asks = json.loads(raw_data)
100 | except Exception :
101 | pass
102 |
103 | if bids_asks:
104 | ask_list = [ [ int(float(o[0]) * 1e8 * (1. + sell_fee) ) , int(o[1] * 1e8) ] for o in bids_asks['asks'] ]
105 | bid_list = [ [ int(float(o[0]) * 1e8 * (1. + buy_fee) ) , int(o[1] * 1e8) ] for o in bids_asks['bids'] ]
106 | arbitrator.process_ask_list(ask_list)
107 | arbitrator.process_bid_list(bid_list)
108 | except urllib2.URLError as e:
109 | print datetime.datetime.now(), e
110 |
111 | except KeyboardInterrupt:
112 | arbitrator.cancel_all_orders()
113 | print 'wait....'
114 | sleep(5)
115 | arbitrator.close()
116 | break
117 |
118 | main()
119 |
120 |
--------------------------------------------------------------------------------
/tools/arbitrage/hitbtc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 |
16 | HITBTC_API_KEY = 'XXXX'
17 | HITBTC_API_SECRET = 'YYYY'
18 |
19 | def send_order(sender, order):
20 | nonce = datetime.datetime.now().strftime('%s')
21 | message = 'sendorder' + str(HITBTC_API_KEY) + str(nonce)
22 | signature = hmac.new(HITBTC_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
23 |
24 | post_params = {
25 | 'key': HITBTC_API_KEY,
26 | 'sign': signature,
27 | 'pair': 'btc_brl',
28 | 'volume': float(order['OrderQty']/1.e8),
29 | 'price': float( order['Price'] / 1.e8)
30 | }
31 |
32 | if order['Side'] == '1':
33 | post_params['type'] = 'buy'
34 | elif order['Side'] == '2':
35 | post_params['type'] = 'sell'
36 |
37 | print datetime.datetime.now(), 'POST https://api.hitbtc.com/v1/tapi/' + message, str(post_params)
38 |
39 | def main():
40 | candidates = ['arbitrage.ini', 'hitbtc.ini' ]
41 | if len(sys.argv) > 1:
42 | candidates.append(sys.argv[1])
43 |
44 |
45 | config = ConfigParser.SafeConfigParser({
46 | 'websocket_url': 'wss://127.0.0.1/trade/',
47 | 'username': '',
48 | 'password': '',
49 | 'buy_fee': 0,
50 | 'sell_fee': 0,
51 | 'api_key': 'KEY',
52 | 'api_secret': 'SECRET'
53 | })
54 | config.read( candidates )
55 |
56 | websocket_url = config.get('hitbtc', 'websocket_url')
57 | username = config.get('hitbtc', 'username')
58 | password = config.get('hitbtc', 'password')
59 | buy_fee = int(config.get('hitbtc', 'buy_fee'))
60 | sell_fee = int(config.get('hitbtc', 'sell_fee'))
61 | api_key = config.get('hitbtc', 'api_key')
62 | api_secret = config.get('hitbtc', 'api_secret')
63 | broker_id = config.getint('hitbtc', 'broker_id')
64 | dest_market = config.get('hitbtc', 'dest_market')
65 |
66 |
67 | arbitrator = BlinkTradeArbitrator(broker_id, username,password,websocket_url, dest_market)
68 | arbitrator.connect()
69 |
70 | arbitrator.signal_order.connect(send_order)
71 |
72 | while True:
73 | try:
74 | sleep(1)
75 | if arbitrator.is_connected():
76 | arbitrator.send_testRequest()
77 | else:
78 | try:
79 | arbitrator.reconnect()
80 | except HandshakeError,e:
81 | continue
82 |
83 | try:
84 | raw_data = urllib2.urlopen('https://api.hitbtc.com/api/1/public/BTCUSD/orderbook?format_price=number&format_amount=number').read()
85 | except Exception:
86 | print 'ERROR RETRIEVING ORDER BOOK'
87 | continue
88 |
89 |
90 | bids_asks = []
91 | try:
92 | bids_asks = json.loads(raw_data)
93 | except Exception :
94 | pass
95 |
96 | if bids_asks:
97 | bid_list = [ [ int(float(o[0]) * 1e8 * (1. + buy_fee) ) , int( float(o[1]) * 1e8) ] for o in bids_asks['bids'] ]
98 | ask_list = [ [ int(float(o[0]) * 1e8 * (1. + sell_fee) ) , int( float(o[1]) * 1e8) ] for o in bids_asks['asks'] ]
99 | arbitrator.process_ask_list(ask_list)
100 | arbitrator.process_bid_list(bid_list)
101 | except urllib2.URLError as e:
102 | print datetime.datetime.now(), e
103 |
104 | except KeyboardInterrupt:
105 | arbitrator.cancel_all_orders()
106 | print 'wait....'
107 | sleep(5)
108 | arbitrator.close()
109 | break
110 |
111 | main()
112 |
113 |
--------------------------------------------------------------------------------
/tools/arbitrage/itbit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 |
16 | ITBIT_API_KEY = 'XXXX'
17 | ITBIT_API_SECRET = 'YYYY'
18 |
19 | def send_order(sender, order):
20 | nonce = datetime.datetime.now().strftime('%s')
21 | message = 'sendorder' + str(ITBIT_API_KEY) + str(nonce)
22 | signature = hmac.new(ITBIT_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
23 |
24 | post_params = {
25 | 'key': ITBIT_API_KEY,
26 | 'sign': signature,
27 | 'pair': 'btc_brl',
28 | 'volume': float(order['OrderQty']/1.e8),
29 | 'price': float( order['Price'] / 1.e8)
30 | }
31 |
32 | if order['Side'] == '1':
33 | post_params['type'] = 'buy'
34 | elif order['Side'] == '2':
35 | post_params['type'] = 'sell'
36 |
37 | print datetime.datetime.now(), 'POST https://api.hitbtc.com/v1/tapi/' + message, str(post_params)
38 |
39 | def main():
40 | candidates = ['arbitrage.ini', 'itbit.ini' ]
41 | if len(sys.argv) > 1:
42 | candidates.append(sys.argv[1])
43 |
44 |
45 | config = ConfigParser.SafeConfigParser({
46 | 'websocket_url': 'wss://127.0.0.1/trade/',
47 | 'username': '',
48 | 'password': '',
49 | 'buy_fee': 0,
50 | 'sell_fee': 0,
51 | 'api_key': 'KEY',
52 | 'api_secret': 'SECRET'
53 | })
54 | config.read( candidates )
55 |
56 | websocket_url = config.get('itbit', 'websocket_url')
57 | username = config.get('itbit', 'username')
58 | password = config.get('itbit', 'password')
59 | buy_fee = float(config.get('itbit', 'buy_fee'))
60 | sell_fee = float(config.get('itbit', 'sell_fee'))
61 | api_key = config.get('itbit', 'api_key')
62 | api_secret = config.get('itbit', 'api_secret')
63 | broker_id = config.getint('itbit', 'broker_id')
64 | dest_market = config.get('itbit', 'dest_market')
65 |
66 | arbitrator = BlinkTradeArbitrator(broker_id,username,password,websocket_url, dest_market )
67 | arbitrator.connect()
68 |
69 | arbitrator.signal_order.connect(send_order)
70 |
71 | while True:
72 | try:
73 | sleep(1)
74 | if arbitrator.is_connected():
75 | arbitrator.send_testRequest()
76 | else:
77 | try:
78 | arbitrator.reconnect()
79 | except HandshakeError,e:
80 | continue
81 |
82 | try:
83 | raw_data = urllib2.urlopen('https://www.itbit.com/api/v2/markets/XBTUSD/orders').read()
84 | except Exception:
85 | print 'ERROR RETRIEVING ORDER BOOK'
86 | continue
87 |
88 |
89 | bids_asks = []
90 | try:
91 | bids_asks = json.loads(raw_data)
92 | except Exception :
93 | pass
94 |
95 | if bids_asks:
96 | bid_list = [ [ int(float(o[0]) * 1e8 * (1. + buy_fee) ) , int( float(o[1]) * 1e8) ] for o in bids_asks['bids'] ]
97 | ask_list = [ [ int(float(o[0]) * 1e8 * (1. + sell_fee) ) , int( float(o[1]) * 1e8) ] for o in bids_asks['asks'] ]
98 | arbitrator.process_ask_list(ask_list)
99 | arbitrator.process_bid_list(bid_list)
100 | except urllib2.URLError as e:
101 | print datetime.datetime.now(), e
102 |
103 | except KeyboardInterrupt:
104 | arbitrator.cancel_all_orders()
105 | print 'wait....'
106 | sleep(5)
107 | arbitrator.close()
108 | break
109 |
110 | main()
111 |
112 |
--------------------------------------------------------------------------------
/tools/arbitrage/mb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import urllib2
4 | from time import sleep
5 | import json
6 |
7 | from arbitrator import BlinkTradeArbitrator
8 |
9 | import datetime
10 | import hmac
11 | import hashlib
12 | import ConfigParser
13 | from ws4py.exc import HandshakeError
14 |
15 |
16 | MB_API_KEY = 'XXXX'
17 | MB_API_SECRET = 'YYYY'
18 |
19 | def send_order_to_MB(sender, order):
20 | nonce = datetime.datetime.now().strftime('%s')
21 | message = 'sendorder' + str(MB_API_KEY) + str(nonce)
22 | signature = hmac.new(MB_API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
23 |
24 | post_params = {
25 | 'key': MB_API_KEY,
26 | 'sign': signature,
27 | 'pair': 'btc_brl',
28 | 'volume': float(order['OrderQty']/1.e8),
29 | 'price': float( order['Price'] / 1.e8)
30 | }
31 |
32 | if msg['Side'] == '1':
33 | post_params['type'] = 'buy'
34 | elif msg['Side'] == '2':
35 | post_params['type'] = 'sell'
36 |
37 | print datetime.datetime.now(), 'POST https://www.mercadobitcoin.com.br/tapi/' + message, str(post_params)
38 |
39 | def main():
40 | candidates = ['arbitrage.ini', 'mb.ini' ]
41 | if len(sys.argv) > 1:
42 | candidates.append(sys.argv[1])
43 |
44 |
45 | config = ConfigParser.SafeConfigParser({
46 | 'websocket_url': 'wss://127.0.0.1/trade/',
47 | 'username': '',
48 | 'password': '',
49 | 'buy_fee': 0,
50 | 'sell_fee': 0,
51 | 'api_key': 'KEY',
52 | 'api_secret': 'SECRET'
53 | })
54 | config.read( candidates )
55 |
56 | websocket_url = config.get('mb', 'websocket_url')
57 | username = config.get('mb', 'username')
58 | password = config.get('mb', 'password')
59 | buy_fee = int(config.get('mb', 'buy_fee'))
60 | sell_fee = int(config.get('mb', 'sell_fee'))
61 | api_key = config.get('mb', 'api_key')
62 | api_secret = config.get('mb', 'api_secret')
63 | broker_id = config.getint('mb', 'broker_id')
64 | dest_market = config.get('mb', 'dest_market')
65 |
66 | print 'websocket_url:', websocket_url
67 | print 'username:', username
68 | print 'buy_fee:', buy_fee
69 | print 'sell_fee:', sell_fee
70 |
71 | arbitrator = BlinkTradeArbitrator(broker_id, username,password,websocket_url, dest_market)
72 | arbitrator.connect()
73 |
74 | arbitrator.signal_order.connect(send_order_to_MB)
75 |
76 | while True:
77 | try:
78 | sleep(5)
79 | if arbitrator.is_connected():
80 | arbitrator.send_testRequest()
81 | else:
82 | try:
83 | arbitrator.reconnect()
84 | except HandshakeError,e:
85 | continue
86 |
87 | try:
88 | raw_data = urllib2.urlopen('https://www.mercadobitcoin.com.br/api/orderbook/').read()
89 | except Exception:
90 | print 'ERROR RETRIEVING ORDER BOOK'
91 | continue
92 |
93 | bids_asks = []
94 | try:
95 | bids_asks = json.loads(raw_data)
96 | except Exception :
97 | pass
98 |
99 | if bids_asks:
100 | ask_list = [ [ int(float(o[0]) * 1e8 * (1. + sell_fee) ) , int(o[1] * 1e8) ] for o in bids_asks['asks'] ]
101 | bid_list = [ [ int(float(o[0]) * 1e8 * (1. + buy_fee) ) , int(o[1] * 1e8) ] for o in bids_asks['bids'] ]
102 | arbitrator.process_ask_list(ask_list)
103 | arbitrator.process_bid_list(bid_list)
104 |
105 | except urllib2.URLError as e:
106 | print datetime.datetime.now(), e
107 |
108 | except KeyboardInterrupt:
109 | arbitrator.cancel_all_orders()
110 | print 'wait....'
111 | sleep(5)
112 | arbitrator.close()
113 | break
114 |
115 | main()
116 |
117 |
--------------------------------------------------------------------------------
/tools/arbitrage/order_book_processor.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.insert(0, '../../libs')
3 |
4 | from pyblinktrade.signals import Signal
5 | import datetime
6 | import time
7 | import random
8 |
9 | class OrderBookProcessor():
10 | def __init__(self, side, symbol):
11 | self.side = side
12 | self.symbol = symbol
13 | self.orders_by_id = {}
14 | self.orders_by_price = {}
15 | self.orders_list_ordered_by_timestamp = []
16 |
17 | self.send_new_order_signal = Signal()
18 | self.cancel_order_signal = Signal()
19 |
20 | def _get_order_by_price(self, price):
21 | if price in self.orders_by_price:
22 | return self.orders_by_price[price]
23 | return None
24 |
25 | def _send_new_order(self, price, volume):
26 | now = datetime.datetime.now()
27 | timestamp = time.mktime(now.timetuple())*1e3 + now.microsecond/1e3
28 |
29 | order_id = str(int(timestamp)) + str(int(random.random()*100000))
30 |
31 | order = { 'id': order_id, 'price': price, 'vol': volume , 'ts': timestamp }
32 | self.orders_by_price[price] = order
33 | self.orders_by_id[order_id] = order
34 |
35 | self.orders_list_ordered_by_timestamp.append( order )
36 |
37 | order_message = {
38 | 'MsgType': 'D',
39 | 'Symbol' : self.symbol,
40 | 'OrdType':'2',
41 | 'Price': int(price),
42 | 'OrderQty': int(volume),
43 | 'ClOrdID': str(order_id),
44 | 'Side': self.side,
45 | }
46 | self.send_new_order_signal( self, order_message)
47 |
48 | return order_id
49 |
50 | def _send_cancel_replace_order(self, order_id, new_volume):
51 | original_order = self.orders_by_id[order_id]
52 |
53 | original_volume = original_order['vol']
54 | if original_volume != new_volume:
55 | self._cancel_order( original_order['id'] )
56 | return self._send_new_order( original_order['price'], new_volume )
57 | else:
58 | # nothing to do ... let's just update the current order timestamp.
59 | now = datetime.datetime.now()
60 | new_timestamp = time.mktime(now.timetuple())*1e3 + now.microsecond/1e3
61 | original_order['ts'] = new_timestamp
62 |
63 | pos = 0
64 | for order in self.orders_list_ordered_by_timestamp:
65 | if order['id'] == order_id:
66 | break
67 | pos += 1
68 | del self.orders_list_ordered_by_timestamp[pos]
69 | self.orders_list_ordered_by_timestamp.append( original_order )
70 |
71 | def _get_last_timestamp(self):
72 | if not self.orders_list_ordered_by_timestamp:
73 | now = datetime.datetime.now()
74 | timestamp = time.mktime(now.timetuple())*1e3 + now.microsecond/1e3
75 | return timestamp
76 | return self.orders_list_ordered_by_timestamp[-1]['ts']
77 |
78 | def _cancel_all_orders_prior_timestamp(self, timestamp):
79 | orders_to_cancel = []
80 | for order in self.orders_list_ordered_by_timestamp:
81 | if order['ts'] <= timestamp:
82 | orders_to_cancel.append(order['id'])
83 |
84 | for order_id in orders_to_cancel:
85 | self._cancel_order( order_id )
86 |
87 | def _cancel_order(self, order_id):
88 | original_order = self.orders_by_id[order_id]
89 |
90 | self.cancel_order_signal(self, { 'MsgType':'F', 'OrigClOrdID': str(order_id)} )
91 |
92 | # find the order position
93 | pos = 0
94 | for order in self.orders_list_ordered_by_timestamp:
95 | if order['id'] == order_id:
96 | break
97 | pos += 1
98 | del self.orders_list_ordered_by_timestamp[pos]
99 |
100 | del self.orders_by_price[original_order['price']]
101 | del self.orders_by_id[original_order['id'] ]
102 | return True
103 |
104 | def process_order_list(self, order_list):
105 | bid_timestamp = self._get_last_timestamp()
106 | for o in order_list:
107 | order_volume = o[1]
108 | order_price = o[0]
109 |
110 | # get the order using the price
111 | order = self._get_order_by_price(order_price)
112 | if order:
113 | if not order_volume:
114 | self._cancel_order(order['id'])
115 | else:
116 | self._send_cancel_replace_order( order['id'], order_volume )
117 | else:
118 | if order_price and order_volume:
119 | self._send_new_order(order_price, order_volume)
120 | self._cancel_all_orders_prior_timestamp(bid_timestamp)
121 |
--------------------------------------------------------------------------------
/tools/arbitrage/util.py:
--------------------------------------------------------------------------------
1 | def get_funded_entries(orders, balance, is_total_vol):
2 | total_vol_usd = 0
3 | total_vol_btc = 0
4 | funded_entries = []
5 | for price_usd, size_btc in orders:
6 | vol_usd = (price_usd * size_btc) / 1e8
7 | previous_total_vol_btc = total_vol_btc
8 | previous_total_vol_usd = total_vol_usd
9 | total_vol_usd += vol_usd
10 | total_vol_btc += size_btc
11 | if is_total_vol:
12 | if total_vol_usd > balance:
13 | available_volume = balance - previous_total_vol_usd
14 | if available_volume:
15 | funded_entries.append([ price_usd, int( (float (available_volume) / float (price_usd)) * 1.e8) ])
16 | break
17 | else:
18 | if total_vol_btc > balance:
19 | if balance-previous_total_vol_btc:
20 | funded_entries.append([ price_usd, int(balance-previous_total_vol_btc) ])
21 | break
22 | funded_entries.append([ price_usd, size_btc ])
23 | return funded_entries
24 |
25 |
26 | def aggregate_orders(order_list):
27 | res = []
28 | for price, size in order_list:
29 | if res:
30 | if res[-1][0] == price:
31 | res[-1][1] += size
32 | else:
33 | res.append( [ price, size ] )
34 | else:
35 | res.append( [ price, size ] )
36 | return res
37 |
--------------------------------------------------------------------------------
/tools/latency_analyser/gw_latency_analyser.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import fileinput
3 | import sys
4 | import json
5 | import datetime
6 | import csv
7 |
8 | cancel_order_dict = {}
9 | new_order_single_dict = {}
10 |
11 | line_number = 0
12 |
13 | csv_file = open(sys.argv[2], 'wt')
14 | csv_writer = csv.writer(csv_file)
15 | csv_writer.writerow( ('Timestamp','LineNumber', 'MessageType', 'ClOrdID', 'Latency(ms)') )
16 |
17 | def latency_in_ms(t1, t2):
18 | return ( t2 - t1 ).microseconds / 1000
19 |
20 | for line in fileinput.input(sys.argv[1]):
21 | timestamp = line[:23]
22 | timestamp = datetime.datetime.strptime(timestamp + '000', "%Y-%m-%d %H:%M:%S,%f")
23 |
24 |
25 | line_number += 1
26 |
27 | log_data = line[26:].split(',')
28 | if len(log_data) > 2:
29 | log_type = log_data[0]
30 | session = log_data[1]
31 | message = log_data[2]
32 | message_start_index = line.find(message)
33 | message = line[message_start_index:]
34 |
35 | try:
36 | message = json.loads(message)
37 | log_record = [timestamp, log_type, session, message ]
38 |
39 |
40 | if 'MsgType' in message and message['MsgType'] == 'F':
41 | cancel_order_dict[ message['OrigClOrdID'] ] = log_record
42 |
43 | if 'MsgType' in message and message['MsgType'] == 'D':
44 | new_order_single_dict[ message['ClOrdID'] ] = log_record
45 |
46 |
47 | if 'MsgType' in message and message['MsgType'] == '8':
48 | if message['ExecType'] == '4':
49 | if message['ClOrdID'] in cancel_order_dict:
50 | latency = latency_in_ms(cancel_order_dict[ message['ClOrdID'] ][0], timestamp)
51 | row = (timestamp, line_number, 'CANCEL_ORDER', message['ClOrdID'], latency )
52 | csv_writer.writerow( row )
53 | del cancel_order_dict[ message['ClOrdID'] ]
54 |
55 | if message['ExecType'] == '0':
56 | if message['ClOrdID'] in new_order_single_dict:
57 | latency = latency_in_ms(new_order_single_dict[ message['ClOrdID'] ][0], timestamp)
58 | row = (timestamp, line_number, 'NEW_ORDER', message['ClOrdID'], latency )
59 | csv_writer.writerow( row )
60 | del new_order_single_dict[ message['ClOrdID'] ]
61 |
62 | #print line_number, timestamp, log_type, session, message
63 | except Exception,e :
64 | pass
65 |
--------------------------------------------------------------------------------