pdmt5 0.1.8__py3-none-any.whl → 0.1.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pdmt5/trading.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from datetime import timedelta
|
|
6
|
+
from functools import cached_property
|
|
6
7
|
from math import floor
|
|
7
8
|
from typing import TYPE_CHECKING, Any, Literal
|
|
8
9
|
|
|
@@ -28,6 +29,67 @@ class Mt5TradingClient(Mt5DataClient):
|
|
|
28
29
|
|
|
29
30
|
model_config = ConfigDict(frozen=True)
|
|
30
31
|
|
|
32
|
+
@cached_property
|
|
33
|
+
def mt5_successful_trade_retcodes(self) -> set[int]:
|
|
34
|
+
"""Set of successful trade return codes.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Set of successful trade return codes.
|
|
38
|
+
"""
|
|
39
|
+
return {
|
|
40
|
+
self.mt5.TRADE_RETCODE_PLACED, # 10008
|
|
41
|
+
self.mt5.TRADE_RETCODE_DONE, # 10009
|
|
42
|
+
self.mt5.TRADE_RETCODE_DONE_PARTIAL, # 10010
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@cached_property
|
|
46
|
+
def mt5_failed_trade_retcodes(self) -> set[int]:
|
|
47
|
+
"""Set of failed trade return codes.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Set of failed trade return codes.
|
|
51
|
+
"""
|
|
52
|
+
return {
|
|
53
|
+
self.mt5.TRADE_RETCODE_REQUOTE, # 10004
|
|
54
|
+
self.mt5.TRADE_RETCODE_REJECT, # 10006
|
|
55
|
+
self.mt5.TRADE_RETCODE_CANCEL, # 10007
|
|
56
|
+
self.mt5.TRADE_RETCODE_ERROR, # 10011
|
|
57
|
+
self.mt5.TRADE_RETCODE_TIMEOUT, # 10012
|
|
58
|
+
self.mt5.TRADE_RETCODE_INVALID, # 10013
|
|
59
|
+
self.mt5.TRADE_RETCODE_INVALID_VOLUME, # 10014
|
|
60
|
+
self.mt5.TRADE_RETCODE_INVALID_PRICE, # 10015
|
|
61
|
+
self.mt5.TRADE_RETCODE_INVALID_STOPS, # 10016
|
|
62
|
+
self.mt5.TRADE_RETCODE_TRADE_DISABLED, # 10017
|
|
63
|
+
self.mt5.TRADE_RETCODE_MARKET_CLOSED, # 10018
|
|
64
|
+
self.mt5.TRADE_RETCODE_NO_MONEY, # 10019
|
|
65
|
+
self.mt5.TRADE_RETCODE_PRICE_CHANGED, # 10020
|
|
66
|
+
self.mt5.TRADE_RETCODE_PRICE_OFF, # 10021
|
|
67
|
+
self.mt5.TRADE_RETCODE_INVALID_EXPIRATION, # 10022
|
|
68
|
+
self.mt5.TRADE_RETCODE_ORDER_CHANGED, # 10023
|
|
69
|
+
self.mt5.TRADE_RETCODE_TOO_MANY_REQUESTS, # 10024
|
|
70
|
+
self.mt5.TRADE_RETCODE_NO_CHANGES, # 10025
|
|
71
|
+
self.mt5.TRADE_RETCODE_SERVER_DISABLES_AT, # 10026
|
|
72
|
+
self.mt5.TRADE_RETCODE_CLIENT_DISABLES_AT, # 10027
|
|
73
|
+
self.mt5.TRADE_RETCODE_LOCKED, # 10028
|
|
74
|
+
self.mt5.TRADE_RETCODE_FROZEN, # 10029
|
|
75
|
+
self.mt5.TRADE_RETCODE_INVALID_FILL, # 10030
|
|
76
|
+
self.mt5.TRADE_RETCODE_CONNECTION, # 10031
|
|
77
|
+
self.mt5.TRADE_RETCODE_ONLY_REAL, # 10032
|
|
78
|
+
self.mt5.TRADE_RETCODE_LIMIT_ORDERS, # 10033
|
|
79
|
+
self.mt5.TRADE_RETCODE_LIMIT_VOLUME, # 10034
|
|
80
|
+
self.mt5.TRADE_RETCODE_INVALID_ORDER, # 10035
|
|
81
|
+
self.mt5.TRADE_RETCODE_POSITION_CLOSED, # 10036
|
|
82
|
+
self.mt5.TRADE_RETCODE_INVALID_CLOSE_VOLUME, # 10038
|
|
83
|
+
self.mt5.TRADE_RETCODE_CLOSE_ORDER_EXIST, # 10039
|
|
84
|
+
self.mt5.TRADE_RETCODE_LIMIT_POSITIONS, # 10040
|
|
85
|
+
self.mt5.TRADE_RETCODE_REJECT_CANCEL, # 10041
|
|
86
|
+
self.mt5.TRADE_RETCODE_LONG_ONLY, # 10042
|
|
87
|
+
self.mt5.TRADE_RETCODE_SHORT_ONLY, # 10043
|
|
88
|
+
self.mt5.TRADE_RETCODE_CLOSE_ONLY, # 10044
|
|
89
|
+
self.mt5.TRADE_RETCODE_FIFO_CLOSE, # 10045
|
|
90
|
+
self.mt5.TRADE_RETCODE_HEDGE_PROHIBITED, # 10046
|
|
91
|
+
}
|
|
92
|
+
|
|
31
93
|
def close_open_positions(
|
|
32
94
|
self,
|
|
33
95
|
symbols: str | list[str] | tuple[str, ...] | None = None,
|
|
@@ -116,12 +178,14 @@ class Mt5TradingClient(Mt5DataClient):
|
|
|
116
178
|
def _send_or_check_order(
|
|
117
179
|
self,
|
|
118
180
|
request: dict[str, Any],
|
|
181
|
+
raise_on_error: bool = False,
|
|
119
182
|
dry_run: bool = False,
|
|
120
183
|
) -> dict[str, Any]:
|
|
121
184
|
"""Send or check an order request.
|
|
122
185
|
|
|
123
186
|
Args:
|
|
124
187
|
request: Order request dictionary.
|
|
188
|
+
raise_on_error: If True, raise an error on operation failure.
|
|
125
189
|
dry_run: If True, only check the order without sending it.
|
|
126
190
|
|
|
127
191
|
Returns:
|
|
@@ -138,25 +202,21 @@ class Mt5TradingClient(Mt5DataClient):
|
|
|
138
202
|
response = self.order_send_as_dict(request=request)
|
|
139
203
|
order_func = "order_send"
|
|
140
204
|
retcode = response.get("retcode")
|
|
141
|
-
if (
|
|
142
|
-
dry_run and retcode
|
|
205
|
+
if (dry_run and retcode == 0) or (
|
|
206
|
+
not dry_run and retcode in self.mt5_successful_trade_retcodes
|
|
143
207
|
):
|
|
144
208
|
self.logger.info("response: %s", response)
|
|
145
209
|
return response
|
|
146
|
-
elif
|
|
147
|
-
self.mt5.TRADE_RETCODE_TRADE_DISABLED,
|
|
148
|
-
self.mt5.TRADE_RETCODE_MARKET_CLOSED,
|
|
149
|
-
self.mt5.TRADE_RETCODE_NO_CHANGES,
|
|
150
|
-
}:
|
|
151
|
-
self.logger.info("response: %s", response)
|
|
152
|
-
comment = response.get("comment", "Unknown error")
|
|
153
|
-
self.logger.warning("%s() failed and skipped. <= `%s`", order_func, comment)
|
|
154
|
-
return response
|
|
155
|
-
else:
|
|
210
|
+
elif raise_on_error:
|
|
156
211
|
self.logger.error("response: %s", response)
|
|
157
|
-
comment = response.get("comment"
|
|
212
|
+
comment = response.get("comment")
|
|
158
213
|
error_message = f"{order_func}() failed and aborted. <= `{comment}`"
|
|
159
214
|
raise Mt5TradingError(error_message)
|
|
215
|
+
else:
|
|
216
|
+
self.logger.warning("response: %s", response)
|
|
217
|
+
comment = response.get("comment")
|
|
218
|
+
self.logger.warning("%s() failed and skipped. <= `%s`", order_func, comment)
|
|
219
|
+
return response
|
|
160
220
|
|
|
161
221
|
def place_market_order(
|
|
162
222
|
self,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdmt5
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Pandas-based data handler for MetaTrader 5
|
|
5
5
|
Project-URL: Repository, https://github.com/dceoy/pdmt5.git
|
|
6
6
|
Author-email: dceoy <dceoy@users.noreply.github.com>
|
|
@@ -53,14 +53,14 @@ Pandas-based data handler for MetaTrader 5
|
|
|
53
53
|
|
|
54
54
|
## Installation
|
|
55
55
|
|
|
56
|
-
###
|
|
56
|
+
### Using pip
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
|
|
60
|
-
pip install -U
|
|
59
|
+
pip install -U pdmt5
|
|
60
|
+
pip install -U MetaTrader5
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
### Using uv
|
|
63
|
+
### Using uv
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
git clone https://github.com/dceoy/pdmt5.git
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
pdmt5/__init__.py,sha256=QbSFrsi7_bgFzb-ma4DmmUjR90UvrqKMnRZq1wPRmoI,446
|
|
2
2
|
pdmt5/dataframe.py,sha256=rUWtR23hrXBdBqzJhbOlIemNy73RrjSTZZJUhwoL6io,38084
|
|
3
3
|
pdmt5/mt5.py,sha256=KgxHapIrh5b4L0wIOAQIjfXNZafalihbFrh9fhYHmrI,32254
|
|
4
|
-
pdmt5/trading.py,sha256=
|
|
4
|
+
pdmt5/trading.py,sha256=U_6h8yR54-5_S_3hmYlAiaNT87fqeb5AK4sUWLThnf8,23433
|
|
5
5
|
pdmt5/utils.py,sha256=Ll5Q3OE5h1A_sZ_qVEnOPGniFlT6_MmHfuu0zqeLdeU,3913
|
|
6
|
-
pdmt5-0.1.
|
|
7
|
-
pdmt5-0.1.
|
|
8
|
-
pdmt5-0.1.
|
|
9
|
-
pdmt5-0.1.
|
|
6
|
+
pdmt5-0.1.9.dist-info/METADATA,sha256=3nWXNUqiPNDE5jMs7s_IPhtNBAdnVVMvhK1D_1mCij4,16109
|
|
7
|
+
pdmt5-0.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
+
pdmt5-0.1.9.dist-info/licenses/LICENSE,sha256=iABrdaUGOBWLYotFupB_PGe8arV5o7rVhn-_vK6P704,1073
|
|
9
|
+
pdmt5-0.1.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|