aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-01 14:12:03 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-01 14:12:03 +0100
commit3f41520799b97b3c440a6daeba684a6202e5a678 (patch)
tree257dfe99d5a15b89f8f22a69ce401e14f50f39db
parentaca4d4372553110ab5d76740ff536de83d5617b2 (diff)
downloadTrader-3f41520799b97b3c440a6daeba684a6202e5a678.tar.gz
Trader-3f41520799b97b3c440a6daeba684a6202e5a678.tar.zst
Trader-3f41520799b97b3c440a6daeba684a6202e5a678.zip
Add tests for ccxt_wrapper
-rw-r--r--ccxt_wrapper.py131
-rw-r--r--test.py81
2 files changed, 153 insertions, 59 deletions
diff --git a/ccxt_wrapper.py b/ccxt_wrapper.py
index 903bfc4..d37c306 100644
--- a/ccxt_wrapper.py
+++ b/ccxt_wrapper.py
@@ -11,29 +11,6 @@ class poloniexE(poloniex):
11 def nanoseconds(): 11 def nanoseconds():
12 return int(time.time() * 1000000000) 12 return int(time.time() * 1000000000)
13 13
14 def nonce(self):
15 return self.nanoseconds()
16
17 def fetch_balance(self, params={}):
18 self.load_markets()
19 balances = self.privatePostReturnCompleteBalances(self.extend({
20 'account': 'all',
21 }, params))
22 result = {'info': balances}
23 currencies = list(balances.keys())
24 for c in range(0, len(currencies)):
25 id = currencies[c]
26 balance = balances[id]
27 currency = self.common_currency_code(id)
28 account = {
29 'free': decimal.Decimal(balance['available']),
30 'used': decimal.Decimal(balance['onOrders']),
31 'total': decimal.Decimal(0.0),
32 }
33 account['total'] = self.sum(account['free'], account['used'])
34 result[currency] = account
35 return self.parse_balance(result)
36
37 def fetch_margin_balance(self): 14 def fetch_margin_balance(self):
38 """ 15 """
39 portfolio.market.privatePostGetMarginPosition({"currencyPair": "BTC_DASH"}) 16 portfolio.market.privatePostGetMarginPosition({"currencyPair": "BTC_DASH"})
@@ -200,31 +177,8 @@ class poloniexE(poloniex):
200 177
201 return all_balances 178 return all_balances
202 179
203 def parse_ticker(self, ticker, market=None): 180 def create_exchange_order(self, symbol, type, side, amount, price=None, params={}):
204 timestamp = self.milliseconds() 181 return super(poloniexE, self).create_order(symbol, type, side, amount, price=price, params=params)
205 symbol = None
206 if market:
207 symbol = market['symbol']
208 return {
209 'symbol': symbol,
210 'timestamp': timestamp,
211 'datetime': self.iso8601(timestamp),
212 'high': decimal.Decimal(ticker['high24hr']),
213 'low': decimal.Decimal(ticker['low24hr']),
214 'bid': decimal.Decimal(ticker['highestBid']),
215 'ask': decimal.Decimal(ticker['lowestAsk']),
216 'vwap': None,
217 'open': None,
218 'close': None,
219 'first': None,
220 'last': decimal.Decimal(ticker['last']),
221 'change': decimal.Decimal(ticker['percentChange']),
222 'percentage': None,
223 'average': None,
224 'baseVolume': decimal.Decimal(ticker['quoteVolume']),
225 'quoteVolume': decimal.Decimal(ticker['baseVolume']),
226 'info': ticker,
227 }
228 182
229 def create_margin_order(self, symbol, type, side, amount, price=None, lending_rate=None, params={}): 183 def create_margin_order(self, symbol, type, side, amount, price=None, lending_rate=None, params={}):
230 if type == 'market': 184 if type == 'market':
@@ -254,17 +208,6 @@ class poloniexE(poloniex):
254 self.orders[id] = order 208 self.orders[id] = order
255 return self.extend({'info': response}, order) 209 return self.extend({'info': response}, order)
256 210
257 def create_exchange_order(self, symbol, type, side, amount, price=None, params={}):
258 return super(poloniexE, self).create_order(symbol, type, side, amount, price=price, params=params)
259
260 def create_order(self, symbol, type, side, amount, price=None, account="exchange", lending_rate=None, params={}):
261 if account == "exchange":
262 return self.create_exchange_order(symbol, type, side, amount, price=price, params=params)
263 elif account == "margin":
264 return self.create_margin_order(symbol, type, side, amount, price=price, lending_rate=lending_rate, params=params)
265 else:
266 raise NotImplementedError
267
268 def order_precision(self, symbol): 211 def order_precision(self, symbol):
269 return 8 212 return 8
270 213
@@ -324,3 +267,73 @@ class poloniexE(poloniex):
324 "total": decimal.Decimal(summary["totalValue"]), 267 "total": decimal.Decimal(summary["totalValue"]),
325 } 268 }
326 269
270 def nonce(self):
271 """
272 Wrapped to allow nonce with other libraries
273 """
274 return self.nanoseconds()
275
276 def fetch_balance(self, params={}):
277 """
278 Wrapped to get decimals
279 """
280 self.load_markets()
281 balances = self.privatePostReturnCompleteBalances(self.extend({
282 'account': 'all',
283 }, params))
284 result = {'info': balances}
285 currencies = list(balances.keys())
286 for c in range(0, len(currencies)):
287 id = currencies[c]
288 balance = balances[id]
289 currency = self.common_currency_code(id)
290 account = {
291 'free': decimal.Decimal(balance['available']),
292 'used': decimal.Decimal(balance['onOrders']),
293 'total': decimal.Decimal(0.0),
294 }
295 account['total'] = self.sum(account['free'], account['used'])
296 result[currency] = account
297 return self.parse_balance(result)
298
299 def parse_ticker(self, ticker, market=None):
300 """
301 Wrapped to get decimals
302 """
303 timestamp = self.milliseconds()
304 symbol = None
305 if market:
306 symbol = market['symbol']
307 return {
308 'symbol': symbol,
309 'timestamp': timestamp,
310 'datetime': self.iso8601(timestamp),
311 'high': decimal.Decimal(ticker['high24hr']),
312 'low': decimal.Decimal(ticker['low24hr']),
313 'bid': decimal.Decimal(ticker['highestBid']),
314 'ask': decimal.Decimal(ticker['lowestAsk']),
315 'vwap': None,
316 'open': None,
317 'close': None,
318 'first': None,
319 'last': decimal.Decimal(ticker['last']),
320 'change': decimal.Decimal(ticker['percentChange']),
321 'percentage': None,
322 'average': None,
323 'baseVolume': decimal.Decimal(ticker['quoteVolume']),
324 'quoteVolume': decimal.Decimal(ticker['baseVolume']),
325 'info': ticker,
326 }
327
328 def create_order(self, symbol, type, side, amount, price=None, account="exchange", lending_rate=None, params={}):
329 """
330 Wrapped to handle margin and exchange accounts
331 """
332 if account == "exchange":
333 return self.create_exchange_order(symbol, type, side, amount, price=price, params=params)
334 elif account == "margin":
335 return self.create_margin_order(symbol, type, side, amount, price=price, lending_rate=lending_rate, params=params)
336 else:
337 raise NotImplementedError
338
339
diff --git a/test.py b/test.py
index 141c9e0..37b0e88 100644
--- a/test.py
+++ b/test.py
@@ -46,6 +46,87 @@ class WebMockTestCase(unittest.TestCase):
46 super(WebMockTestCase, self).tearDown() 46 super(WebMockTestCase, self).tearDown()
47 47
48@unittest.skipUnless("unit" in limits, "Unit skipped") 48@unittest.skipUnless("unit" in limits, "Unit skipped")
49class poloniexETest(unittest.TestCase):
50 def setUp(self):
51 super(poloniexETest, self).setUp()
52 self.wm = requests_mock.Mocker()
53 self.wm.start()
54
55 self.s = market.ccxt.poloniexE()
56
57 def tearDown(self):
58 self.wm.stop()
59 super(poloniexETest, self).tearDown()
60
61 def test_nanoseconds(self):
62 with mock.patch.object(market.ccxt.time, "time") as time:
63 time.return_value = 123456.7890123456
64 self.assertEqual(123456789012345, self.s.nanoseconds())
65
66 def test_nonce(self):
67 with mock.patch.object(market.ccxt.time, "time") as time:
68 time.return_value = 123456.7890123456
69 self.assertEqual(123456789012345, self.s.nonce())
70
71 def test_order_precision(self):
72 self.assertEqual(8, self.s.order_precision("FOO"))
73
74 def test_transfer_balance(self):
75 with self.subTest(success=True),\
76 mock.patch.object(self.s, "privatePostTransferBalance") as t:
77 t.return_value = { "success": 1 }
78 result = self.s.transfer_balance("FOO", 12, "exchange", "margin")
79 t.assert_called_once_with({
80 "currency": "FOO",
81 "amount": 12,
82 "fromAccount": "exchange",
83 "toAccount": "margin",
84 "confirmed": 1
85 })
86 self.assertTrue(result)
87
88 with self.subTest(success=False),\
89 mock.patch.object(self.s, "privatePostTransferBalance") as t:
90 t.return_value = { "success": 0 }
91 self.assertFalse(self.s.transfer_balance("FOO", 12, "exchange", "margin"))
92
93 def test_close_margin_position(self):
94 with mock.patch.object(self.s, "privatePostCloseMarginPosition") as c:
95 self.s.close_margin_position("FOO", "BAR")
96 c.assert_called_with({"currencyPair": "BAR_FOO"})
97
98 def test_tradable_balances(self):
99 with mock.patch.object(self.s, "privatePostReturnTradableBalances") as r:
100 r.return_value = {
101 "FOO": { "exchange": "12.1234", "margin": "0.0123" },
102 "BAR": { "exchange": "1", "margin": "0" },
103 }
104 balances = self.s.tradable_balances()
105 self.assertEqual(["FOO", "BAR"], list(balances.keys()))
106 self.assertEqual(["exchange", "margin"], list(balances["FOO"].keys()))
107 self.assertEqual(D("12.1234"), balances["FOO"]["exchange"])
108 self.assertEqual(["exchange", "margin"], list(balances["BAR"].keys()))
109
110 def test_margin_summary(self):
111 with mock.patch.object(self.s, "privatePostReturnMarginAccountSummary") as r:
112 r.return_value = {
113 "currentMargin": "1.49680968",
114 "lendingFees": "0.0000001",
115 "pl": "0.00008254",
116 "totalBorrowedValue": "0.00673602",
117 "totalValue": "0.01000000",
118 "netValue": "0.01008254",
119 }
120 expected = {
121 'current_margin': D('1.49680968'),
122 'gains': D('0.00008254'),
123 'lending_fees': D('0.0000001'),
124 'total': D('0.01000000'),
125 'total_borrowed': D('0.00673602')
126 }
127 self.assertEqual(expected, self.s.margin_summary())
128
129@unittest.skipUnless("unit" in limits, "Unit skipped")
49class PortfolioTest(WebMockTestCase): 130class PortfolioTest(WebMockTestCase):
50 def fill_data(self): 131 def fill_data(self):
51 if self.json_response is not None: 132 if self.json_response is not None: