diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-03-04 12:59:57 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-03-04 12:59:57 +0100 |
commit | 17598517c544a3dda8b9f773dfeb669c886ea92b (patch) | |
tree | eb02553743f2aa2cdd64e2b1cdd02d3c02d4a6cd | |
parent | 9db7d156833cd384baa64b6148b5c646bfcc41f8 (diff) | |
download | Trader-17598517c544a3dda8b9f773dfeb669c886ea92b.tar.gz Trader-17598517c544a3dda8b9f773dfeb669c886ea92b.tar.zst Trader-17598517c544a3dda8b9f773dfeb669c886ea92b.zip |
Add close trades action
-rw-r--r-- | helper.py | 3 | ||||
-rw-r--r-- | portfolio.py | 8 | ||||
-rw-r--r-- | store.py | 6 | ||||
-rw-r--r-- | test.py | 56 |
4 files changed, 66 insertions, 7 deletions
@@ -179,6 +179,7 @@ class Processor: | |||
179 | "prepare_orders": { "only": "dispose", "compute_value": "average" }, | 179 | "prepare_orders": { "only": "dispose", "compute_value": "average" }, |
180 | "run_orders": {}, | 180 | "run_orders": {}, |
181 | "follow_orders": {}, | 181 | "follow_orders": {}, |
182 | "close_trades": {}, | ||
182 | }, | 183 | }, |
183 | { | 184 | { |
184 | "name": "buy", | 185 | "name": "buy", |
@@ -191,6 +192,7 @@ class Processor: | |||
191 | "move_balances": {}, | 192 | "move_balances": {}, |
192 | "run_orders": {}, | 193 | "run_orders": {}, |
193 | "follow_orders": {}, | 194 | "follow_orders": {}, |
195 | "close_trades": {}, | ||
194 | }, | 196 | }, |
195 | ], | 197 | ], |
196 | "sell_all": [ | 198 | "sell_all": [ |
@@ -204,6 +206,7 @@ class Processor: | |||
204 | "prepare_orders": { "compute_value": "average" }, | 206 | "prepare_orders": { "compute_value": "average" }, |
205 | "run_orders": {}, | 207 | "run_orders": {}, |
206 | "follow_orders": {}, | 208 | "follow_orders": {}, |
209 | "close_trades": {}, | ||
207 | }, | 210 | }, |
208 | { | 211 | { |
209 | "name": "wait", | 212 | "name": "wait", |
diff --git a/portfolio.py b/portfolio.py index b77850b..f27e84f 100644 --- a/portfolio.py +++ b/portfolio.py | |||
@@ -290,6 +290,7 @@ class Trade: | |||
290 | self.value_to = value_to | 290 | self.value_to = value_to |
291 | self.orders = [] | 291 | self.orders = [] |
292 | self.market = market | 292 | self.market = market |
293 | self.closed = False | ||
293 | assert self.value_from.value * self.value_to.value >= 0 | 294 | assert self.value_from.value * self.value_to.value >= 0 |
294 | assert self.value_from.currency == self.value_to.currency | 295 | assert self.value_from.currency == self.value_to.currency |
295 | if self.value_from != 0: | 296 | if self.value_from != 0: |
@@ -328,6 +329,13 @@ class Trade: | |||
328 | return "long" | 329 | return "long" |
329 | 330 | ||
330 | @property | 331 | @property |
332 | def pending(self): | ||
333 | return not (self.is_fullfiled or self.closed) | ||
334 | |||
335 | def close(self): | ||
336 | self.closed = True | ||
337 | |||
338 | @property | ||
331 | def is_fullfiled(self): | 339 | def is_fullfiled(self): |
332 | return abs(self.filled_amount(in_base_currency=True)) >= abs(self.delta) | 340 | return abs(self.filled_amount(in_base_currency=True)) >= abs(self.delta) |
333 | 341 | ||
@@ -234,7 +234,7 @@ class TradeStore: | |||
234 | 234 | ||
235 | @property | 235 | @property |
236 | def pending(self): | 236 | def pending(self): |
237 | return list(filter(lambda t: not t.is_fullfiled, self.all)) | 237 | return list(filter(lambda t: t.pending, self.all)) |
238 | 238 | ||
239 | def compute_trades(self, values_in_base, new_repartition, only=None): | 239 | def compute_trades(self, values_in_base, new_repartition, only=None): |
240 | computed_trades = [] | 240 | computed_trades = [] |
@@ -275,6 +275,10 @@ class TradeStore: | |||
275 | orders.append(trade.prepare_order(compute_value=compute_value)) | 275 | orders.append(trade.prepare_order(compute_value=compute_value)) |
276 | self.market.report.log_orders(orders, only, compute_value) | 276 | self.market.report.log_orders(orders, only, compute_value) |
277 | 277 | ||
278 | def close_trades(self): | ||
279 | for trade in self.all: | ||
280 | trade.close() | ||
281 | |||
278 | def print_all_with_order(self, ind=""): | 282 | def print_all_with_order(self, ind=""): |
279 | for trade in self.all: | 283 | for trade in self.all: |
280 | trade.print_with_order(ind=ind) | 284 | trade.print_with_order(ind=ind) |
@@ -991,9 +991,9 @@ class TradeStoreTest(WebMockTestCase): | |||
991 | trade_mock2.prepare_order.return_value = 2 | 991 | trade_mock2.prepare_order.return_value = 2 |
992 | trade_mock3.prepare_order.return_value = 3 | 992 | trade_mock3.prepare_order.return_value = 3 |
993 | 993 | ||
994 | trade_mock1.is_fullfiled = False | 994 | trade_mock1.pending = True |
995 | trade_mock2.is_fullfiled = False | 995 | trade_mock2.pending = True |
996 | trade_mock3.is_fullfiled = True | 996 | trade_mock3.pending = False |
997 | 997 | ||
998 | trade_store.all.append(trade_mock1) | 998 | trade_store.all.append(trade_mock1) |
999 | trade_store.all.append(trade_mock2) | 999 | trade_store.all.append(trade_mock2) |
@@ -1100,13 +1100,30 @@ class TradeStoreTest(WebMockTestCase): | |||
1100 | order_mock2.get_status.assert_called() | 1100 | order_mock2.get_status.assert_called() |
1101 | order_mock3.get_status.assert_called() | 1101 | order_mock3.get_status.assert_called() |
1102 | 1102 | ||
1103 | def test_close_trades(self): | ||
1104 | trade_mock1 = mock.Mock() | ||
1105 | trade_mock2 = mock.Mock() | ||
1106 | trade_mock3 = mock.Mock() | ||
1107 | |||
1108 | trade_store = market.TradeStore(self.m) | ||
1109 | |||
1110 | trade_store.all.append(trade_mock1) | ||
1111 | trade_store.all.append(trade_mock2) | ||
1112 | trade_store.all.append(trade_mock3) | ||
1113 | |||
1114 | trade_store.close_trades() | ||
1115 | |||
1116 | trade_mock1.close.assert_called_once_with() | ||
1117 | trade_mock2.close.assert_called_once_with() | ||
1118 | trade_mock3.close.assert_called_once_with() | ||
1119 | |||
1103 | def test_pending(self): | 1120 | def test_pending(self): |
1104 | trade_mock1 = mock.Mock() | 1121 | trade_mock1 = mock.Mock() |
1105 | trade_mock1.is_fullfiled = False | 1122 | trade_mock1.pending = True |
1106 | trade_mock2 = mock.Mock() | 1123 | trade_mock2 = mock.Mock() |
1107 | trade_mock2.is_fullfiled = False | 1124 | trade_mock2.pending = True |
1108 | trade_mock3 = mock.Mock() | 1125 | trade_mock3 = mock.Mock() |
1109 | trade_mock3.is_fullfiled = True | 1126 | trade_mock3.pending = False |
1110 | 1127 | ||
1111 | trade_store = market.TradeStore(self.m) | 1128 | trade_store = market.TradeStore(self.m) |
1112 | 1129 | ||
@@ -1739,6 +1756,33 @@ class TradeTest(WebMockTestCase): | |||
1739 | self.assertEqual("\t\tMouvement 1", str(calls[3][1][0])) | 1756 | self.assertEqual("\t\tMouvement 1", str(calls[3][1][0])) |
1740 | self.assertEqual("\t\tMouvement 2", str(calls[4][1][0])) | 1757 | self.assertEqual("\t\tMouvement 2", str(calls[4][1][0])) |
1741 | 1758 | ||
1759 | def test_close(self): | ||
1760 | value_from = portfolio.Amount("BTC", "0.5") | ||
1761 | value_from.linked_to = portfolio.Amount("ETH", "10.0") | ||
1762 | value_to = portfolio.Amount("BTC", "1.0") | ||
1763 | trade = portfolio.Trade(value_from, value_to, "ETH", self.m) | ||
1764 | |||
1765 | trade.close() | ||
1766 | |||
1767 | self.assertEqual(True, trade.closed) | ||
1768 | |||
1769 | def test_pending(self): | ||
1770 | value_from = portfolio.Amount("BTC", "0.5") | ||
1771 | value_from.linked_to = portfolio.Amount("ETH", "10.0") | ||
1772 | value_to = portfolio.Amount("BTC", "1.0") | ||
1773 | trade = portfolio.Trade(value_from, value_to, "ETH", self.m) | ||
1774 | |||
1775 | trade.closed = True | ||
1776 | self.assertEqual(False, trade.pending) | ||
1777 | |||
1778 | trade.closed = False | ||
1779 | self.assertEqual(True, trade.pending) | ||
1780 | |||
1781 | order1 = mock.Mock() | ||
1782 | order1.filled_amount.return_value = portfolio.Amount("BTC", "0.5") | ||
1783 | trade.orders.append(order1) | ||
1784 | self.assertEqual(False, trade.pending) | ||
1785 | |||
1742 | def test__repr(self): | 1786 | def test__repr(self): |
1743 | value_from = portfolio.Amount("BTC", "0.5") | 1787 | value_from = portfolio.Amount("BTC", "0.5") |
1744 | value_from.linked_to = portfolio.Amount("ETH", "10.0") | 1788 | value_from.linked_to = portfolio.Amount("ETH", "10.0") |