diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-26 00:10:03 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-26 00:13:23 +0100 |
commit | ecba11139e357567c46f7ba2a0cf8dbd98266fe8 (patch) | |
tree | d75d352988833038c3243f1e3e961434ded1bdc6 | |
parent | 66c8b3dd07f4e45be2242d06f8f357adefeb2a4c (diff) | |
download | Trader-ecba11139e357567c46f7ba2a0cf8dbd98266fe8.tar.gz Trader-ecba11139e357567c46f7ba2a0cf8dbd98266fe8.tar.zst Trader-ecba11139e357567c46f7ba2a0cf8dbd98266fe8.zip |
Add first steps for margin trading
-rw-r--r-- | market.py | 53 | ||||
-rw-r--r-- | portfolio.py | 13 | ||||
-rw-r--r-- | test.py | 3 |
3 files changed, 61 insertions, 8 deletions
@@ -25,6 +25,19 @@ def poloniex_fetch_balance(self, params={}): | |||
25 | return self.parse_balance(result) | 25 | return self.parse_balance(result) |
26 | ccxt.poloniex.fetch_balance = poloniex_fetch_balance | 26 | ccxt.poloniex.fetch_balance = poloniex_fetch_balance |
27 | 27 | ||
28 | def poloniex_fetch_balance_per_type(self): | ||
29 | balances = self.privatePostReturnAvailableAccountBalances() | ||
30 | result = {'info': balances} | ||
31 | for key, balance in balances.items(): | ||
32 | result[key] = {} | ||
33 | for currency, amount in balance.items(): | ||
34 | if currency not in result: | ||
35 | result[currency] = {} | ||
36 | result[currency][key] = decimal.Decimal(amount) | ||
37 | result[key][currency] = decimal.Decimal(amount) | ||
38 | return result | ||
39 | ccxt.poloniex.fetch_balance_per_type = poloniex_fetch_balance_per_type | ||
40 | |||
28 | def poloniex_parse_ticker(self, ticker, market=None): | 41 | def poloniex_parse_ticker(self, ticker, market=None): |
29 | timestamp = self.milliseconds() | 42 | timestamp = self.milliseconds() |
30 | symbol = None | 43 | symbol = None |
@@ -51,7 +64,47 @@ def poloniex_parse_ticker(self, ticker, market=None): | |||
51 | 'info': ticker, | 64 | 'info': ticker, |
52 | } | 65 | } |
53 | ccxt.poloniex.parse_ticker = poloniex_parse_ticker | 66 | ccxt.poloniex.parse_ticker = poloniex_parse_ticker |
67 | |||
68 | def poloniex_create_margin_order(self, symbol, type, side, amount, price=None, lending_rate=None, params={}): | ||
69 | if type == 'market': | ||
70 | raise ccxt.ExchangeError(self.id + ' allows limit orders only') | ||
71 | self.load_markets() | ||
72 | method = 'privatePostMargin' + self.capitalize(side) | ||
73 | market = self.market(symbol) | ||
74 | price = float(price) | ||
75 | amount = float(amount) | ||
76 | if lending_rate is not None: | ||
77 | params = self.extend({"lendingRate": lending_rate}, params) | ||
78 | response = getattr(self, method)(self.extend({ | ||
79 | 'currencyPair': market['id'], | ||
80 | 'rate': self.price_to_precision(symbol, price), | ||
81 | 'amount': self.amount_to_precision(symbol, amount), | ||
82 | }, params)) | ||
83 | timestamp = self.milliseconds() | ||
84 | order = self.parse_order(self.extend({ | ||
85 | 'timestamp': timestamp, | ||
86 | 'status': 'open', | ||
87 | 'type': type, | ||
88 | 'side': side, | ||
89 | 'price': price, | ||
90 | 'amount': amount, | ||
91 | }, response), market) | ||
92 | id = order['id'] | ||
93 | self.orders[id] = order | ||
94 | return self.extend({'info': response}, order) | ||
95 | |||
96 | def poloniex_create_order(self, symbol, type, side, amount, price=None, account="exchange", lending_rate=None, params={}): | ||
97 | if account == "exchange": | ||
98 | return self.create_exchange_order(symbol, type, side, amount, price=price, params=params) | ||
99 | elif account == "margin": | ||
100 | return self.create_margin_order(symbol, type, side, amount, price=price, lending_rate=lending_rate, params=params) | ||
101 | else: | ||
102 | raise NotImplementedError | ||
103 | ccxt.poloniex.create_exchange_order = ccxt.poloniex.create_order | ||
104 | ccxt.poloniex.create_order = poloniex_create_order | ||
105 | |||
54 | market = ccxt.poloniex({ | 106 | market = ccxt.poloniex({ |
55 | "apiKey": "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX", | 107 | "apiKey": "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX", |
56 | "secret": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", | 108 | "secret": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", |
57 | }) | 109 | }) |
110 | |||
diff --git a/portfolio.py b/portfolio.py index 1fe56b5..3257bcf 100644 --- a/portfolio.py +++ b/portfolio.py | |||
@@ -467,12 +467,13 @@ class Trade: | |||
467 | print("\t", order, sep="") | 467 | print("\t", order, sep="") |
468 | 468 | ||
469 | class Order: | 469 | class Order: |
470 | def __init__(self, action, amount, rate, base_currency, market): | 470 | def __init__(self, action, amount, rate, base_currency, market, account="exchange"): |
471 | self.action = action | 471 | self.action = action |
472 | self.amount = amount | 472 | self.amount = amount |
473 | self.rate = rate | 473 | self.rate = rate |
474 | self.base_currency = base_currency | 474 | self.base_currency = base_currency |
475 | self.market = market | 475 | self.market = market |
476 | self.account = account | ||
476 | self.result = None | 477 | self.result = None |
477 | self.status = "pending" | 478 | self.status = "pending" |
478 | 479 | ||
@@ -498,16 +499,16 @@ class Order: | |||
498 | amount = self.amount.value | 499 | amount = self.amount.value |
499 | 500 | ||
500 | if debug: | 501 | if debug: |
501 | print("market.create_order('{}', 'limit', '{}', {}, price={})".format( | 502 | print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( |
502 | symbol, self.action, amount, self.rate)) | 503 | symbol, self.action, amount, self.rate, self.account)) |
503 | else: | 504 | else: |
504 | try: | 505 | try: |
505 | self.result = self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate) | 506 | self.result = self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account) |
506 | self.status = "open" | 507 | self.status = "open" |
507 | except Exception as e: | 508 | except Exception as e: |
508 | self.status = "error" | 509 | self.status = "error" |
509 | print("error when running market.create_order('{}', 'limit', '{}', {}, price={})".format( | 510 | print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( |
510 | symbol, self.action, amount, self.rate)) | 511 | symbol, self.action, amount, self.rate, self.account)) |
511 | self.error_message = str("{}: {}".format(e.__class__.__name__, e)) | 512 | self.error_message = str("{}: {}".format(e.__class__.__name__, e)) |
512 | print(self.error_message) | 513 | print(self.error_message) |
513 | 514 | ||
@@ -676,7 +676,7 @@ class AcceptanceTest(unittest.TestCase): | |||
676 | self.assertEqual(D("0.00003003"), all_orders[1].rate) | 676 | self.assertEqual(D("0.00003003"), all_orders[1].rate) |
677 | 677 | ||
678 | 678 | ||
679 | def create_order(symbol, type, action, amount, price=None): | 679 | def create_order(symbol, type, action, amount, price=None, account="exchange"): |
680 | self.assertEqual("limit", type) | 680 | self.assertEqual("limit", type) |
681 | if symbol == "ETH/BTC": | 681 | if symbol == "ETH/BTC": |
682 | self.assertEqual("sell", action) | 682 | self.assertEqual("sell", action) |
@@ -771,7 +771,6 @@ class AcceptanceTest(unittest.TestCase): | |||
771 | # Action 6 | 771 | # Action 6 |
772 | portfolio.Trade.prepare_orders(only="buy", compute_value=lambda x, y: x["ask"]) | 772 | portfolio.Trade.prepare_orders(only="buy", compute_value=lambda x, y: x["ask"]) |
773 | 773 | ||
774 | |||
775 | all_orders = portfolio.Trade.all_orders(state="pending") | 774 | all_orders = portfolio.Trade.all_orders(state="pending") |
776 | self.assertEqual(3, len(all_orders)) | 775 | self.assertEqual(3, len(all_orders)) |
777 | self.assertEqual(portfolio.Amount("ETC", D("38.5")/3), all_orders[0].amount) | 776 | self.assertEqual(portfolio.Amount("ETC", D("38.5")/3), all_orders[0].amount) |