pdmt5 0.1.7__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,24 +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 ((not dry_run) and retcode == self.mt5.TRADE_RETCODE_DONE) or (
142
- dry_run and retcode == 0
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 retcode in {
147
- self.mt5.TRADE_RETCODE_TRADE_DISABLED,
148
- self.mt5.TRADE_RETCODE_MARKET_CLOSED,
149
- }:
150
- self.logger.info("response: %s", response)
151
- comment = response.get("comment", "Unknown error")
152
- self.logger.warning("%s() failed and skipped. <= `%s`", order_func, comment)
153
- return response
154
- else:
210
+ elif raise_on_error:
155
211
  self.logger.error("response: %s", response)
156
- comment = response.get("comment", "Unknown error")
212
+ comment = response.get("comment")
157
213
  error_message = f"{order_func}() failed and aborted. <= `{comment}`"
158
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
159
220
 
160
221
  def place_market_order(
161
222
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdmt5
3
- Version: 0.1.7
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
- ### From GitHub
56
+ ### Using pip
57
57
 
58
58
  ```bash
59
- git clone https://github.com/dceoy/pdmt5.git
60
- pip install -U --no-cache-dir ./pdmt5
59
+ pip install -U pdmt5
60
+ pip install -U MetaTrader5
61
61
  ```
62
62
 
63
- ### Using uv (recommended for development)
63
+ ### Using uv
64
64
 
65
65
  ```bash
66
66
  git clone https://github.com/dceoy/pdmt5.git
@@ -392,7 +392,7 @@ cd pdmt5
392
392
  uv sync
393
393
 
394
394
  # Run tests
395
- uv run pytest test/ -v
395
+ uv run pytest tests/ -v
396
396
 
397
397
  # Run type checking
398
398
  uv run pyright .
@@ -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=LRHfh1bjC_day4A4Az4Q5TM4cBgZB18pWxj3Wfyo5Yg,20608
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.dist-info/METADATA,sha256=c5HJ6Xm3upGHXdGQ3j1sOBE_QHY_kBVCRJJWPdgunt0,16175
7
- pdmt5-0.1.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- pdmt5-0.1.7.dist-info/licenses/LICENSE,sha256=iABrdaUGOBWLYotFupB_PGe8arV5o7rVhn-_vK6P704,1073
9
- pdmt5-0.1.7.dist-info/RECORD,,
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