-
Notifications
You must be signed in to change notification settings - Fork 1
/
goxapi.py
146 lines (124 loc) · 4.24 KB
/
goxapi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""
Common calls to the MtGox API
See https://en.bitcoin.it/wiki/MtGox/API for a more detailed explanation.
"""
import json
import websocket
import time
import hashlib
import hmac
import base64
import ssl
MTGOX_SOCKET = "wss://websocket.mtgox.com/mtgox?Currency=USD"
TIMEOUT = 10
MAX_TIMEOUTS = 10
class GoxAPI():
def __init__(self):
self.socket = None
keydata = open("keydata.conf", "r")
keyjson = json.loads(keydata.read())
self.key = keyjson['key']
self.secret = keyjson['secret']
self.numTimeouts = 0
keydata.close()
def connect(self):
"""Opens a connection to mtGox websocket"""
print "Connecting to MtGox websocket..."
sock = websocket.create_connection(MTGOX_SOCKET, TIMEOUT)
print "Connected!"
subscribe_cmd = "{'op':'mtgox.subscribe', 'type':'lag'}"
sock.send(subscribe_cmd)
sock.recv()
self.socket = sock
return sock
def reconnect(self):
self.socket.close()
print "Max timeouts occurred. Reconnecting to websocket..."
return self.connect()
def getNonce(self):
"""Generates a unique identifier used when placing orders"""
return str(time.time())
def getTrades(self):
"""Attempts to get trades from open mtGox websocket"""
if self.socket is not None:
try:
data = json.loads(self.socket.recv())
except ssl.SSLError:
self.numTimeouts += 1
if (self.numTimeouts == MAX_TIMEOUTS):
self.reconnect()
return None
except Exception:
return None
self.numTimeouts = 0
return data
else:
print "Error: Not connected to mtGox socket"
return None
def buy(self, price, vol):
"""Executes a buy order
price in dollars as float
volume in btc as float
Returns order ID (oid) if successful, False if failed
"""
price = int(price * 1E5)
vol = int(vol * 1E8)
params = {
"type": "bid",
"amount_int": vol,
"price_int": price}
return self.sendSignedCall("order/add", params)
def sell(self, price, vol):
"""Executes a sell order
price in dollars as float
volume in btc as float
Returns order ID (oid) if successful, False if failed
"""
price = int(price * 1E5)
vol = int(vol * 1E8)
params = {
"type": "ask",
"amount_int": vol,
"price_int": price}
return self.sendSignedCall("order/add", params)
def cancel(self, oid):
"""Cancels the order refered by oid"""
params = {
"oid": oid}
return self.sendSignedCall("order/cancel", params)
def sendSignedCall(self, api, params=None):
"""Packages required mtGox API data and sends the command
This is a generic function used by both buy and sell commands
It will return whatever result is specified by the mtGox API if
successful, or False if the call failed
"""
nonce = self.getNonce()
reqId = hashlib.md5(nonce).hexdigest()
req = json.dumps({
"id": reqId,
"call": api,
"nonce": nonce,
"params": params,
"currency": "USD",
"item": "BTC"})
signedReq = hmac.new(base64.b64decode(self.secret), req,
hashlib.sha512).digest()
signedAndEncodedCall = base64.b64encode(self.key.replace("-", "")
.decode("hex") + signedReq + req)
call = json.dumps({
"op": "call",
"call": signedAndEncodedCall,
"id": reqId,
"context": "mtgox.com"})
self.socket.send(call)
while True:
result = json.loads(self.socket.recv())
try:
if (result["id"] == reqId):
try:
if (result["success"] is False):
return False
except Exception, e:
return result["result"]
except Exception, e:
continue