pdmt5 0.1.1__py3-none-any.whl → 0.1.3__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
@@ -2,13 +2,17 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any, Literal
5
+ from datetime import timedelta
6
+ from typing import TYPE_CHECKING, Any, Literal
6
7
 
7
8
  from pydantic import ConfigDict, Field
8
9
 
9
10
  from .dataframe import Mt5DataClient
10
11
  from .mt5 import Mt5RuntimeError
11
12
 
13
+ if TYPE_CHECKING:
14
+ import pandas as pd
15
+
12
16
 
13
17
  class Mt5TradingError(Mt5RuntimeError):
14
18
  """MetaTrader5 trading error."""
@@ -32,6 +36,7 @@ class Mt5TradingClient(Mt5DataClient):
32
36
  def close_open_positions(
33
37
  self,
34
38
  symbols: str | list[str] | tuple[str, ...] | None = None,
39
+ dry_run: bool | None = None,
35
40
  **kwargs: Any, # noqa: ANN401
36
41
  ) -> dict[str, list[dict[str, Any]]]:
37
42
  """Close all open positions for specified symbols.
@@ -39,6 +44,8 @@ class Mt5TradingClient(Mt5DataClient):
39
44
  Args:
40
45
  symbols: Optional symbol or list of symbols to filter positions.
41
46
  If None, all symbols will be considered.
47
+ dry_run: Optional flag to enable dry run mode. If None, uses the instance's
48
+ `dry_run` attribute.
42
49
  **kwargs: Additional keyword arguments for request parameters.
43
50
 
44
51
  Returns:
@@ -53,18 +60,22 @@ class Mt5TradingClient(Mt5DataClient):
53
60
  symbol_list = self.symbols_get()
54
61
  self.logger.info("Fetching and closing positions for symbols: %s", symbol_list)
55
62
  return {
56
- s: self._fetch_and_close_position(symbol=s, **kwargs) for s in symbol_list
63
+ s: self._fetch_and_close_position(symbol=s, dry_run=dry_run, **kwargs)
64
+ for s in symbol_list
57
65
  }
58
66
 
59
67
  def _fetch_and_close_position(
60
68
  self,
61
69
  symbol: str | None = None,
70
+ dry_run: bool | None = None,
62
71
  **kwargs: Any, # noqa: ANN401
63
72
  ) -> list[dict[str, Any]]:
64
73
  """Close all open positions for a specific symbol.
65
74
 
66
75
  Args:
67
76
  symbol: Optional symbol filter.
77
+ dry_run: Optional flag to enable dry run mode. If None, uses the instance's
78
+ `dry_run` attribute.
68
79
  **kwargs: Additional keyword arguments for request parameters.
69
80
 
70
81
  Returns:
@@ -96,6 +107,7 @@ class Mt5TradingClient(Mt5DataClient):
96
107
  "position": p["ticket"],
97
108
  **kwargs,
98
109
  },
110
+ dry_run=dry_run,
99
111
  )
100
112
  for p in positions_dict
101
113
  ]
@@ -182,3 +194,84 @@ class Mt5TradingClient(Mt5DataClient):
182
194
  f"Failed to calculate minimum order margins for symbol: {symbol}."
183
195
  )
184
196
  raise Mt5TradingError(error_message)
197
+
198
+ def calculate_spread_ratio(
199
+ self,
200
+ symbol: str,
201
+ ) -> float:
202
+ """Calculate the spread ratio for a given symbol.
203
+
204
+ Args:
205
+ symbol: Symbol for which to calculate the spread ratio.
206
+
207
+ Returns:
208
+ Spread ratio as a float.
209
+ """
210
+ symbol_info_tick = self.symbol_info_tick_as_dict(symbol=symbol)
211
+ return (
212
+ (symbol_info_tick["ask"] - symbol_info_tick["bid"])
213
+ / (symbol_info_tick["ask"] + symbol_info_tick["bid"])
214
+ * 2
215
+ )
216
+
217
+ def copy_latest_rates_as_df(
218
+ self,
219
+ symbol: str,
220
+ granularity: str = "M1",
221
+ count: int = 1440,
222
+ index_keys: str | None = "time",
223
+ ) -> pd.DataFrame:
224
+ """Fetch rate (OHLC) data as a DataFrame.
225
+
226
+ Args:
227
+ symbol: Symbol to fetch data for.
228
+ granularity: Time granularity as a timeframe suffix (e.g., "M1", "H1").
229
+ count: Number of bars to fetch.
230
+ index_keys: Optional index keys for the DataFrame.
231
+
232
+ Returns:
233
+ pd.DataFrame: OHLC data with time index.
234
+
235
+ Raises:
236
+ Mt5TradingError: If the granularity is not supported by MetaTrader5.
237
+ """
238
+ try:
239
+ timeframe = getattr(self.mt5, f"TIMEFRAME_{granularity.upper()}")
240
+ except AttributeError as e:
241
+ error_message = (
242
+ f"MetaTrader5 does not support the given granularity: {granularity}"
243
+ )
244
+ raise Mt5TradingError(error_message) from e
245
+ else:
246
+ return self.copy_rates_from_pos_as_df(
247
+ symbol=symbol,
248
+ timeframe=timeframe,
249
+ start_pos=0,
250
+ count=count,
251
+ index_keys=index_keys,
252
+ )
253
+
254
+ def copy_latest_ticks_as_df(
255
+ self,
256
+ symbol: str,
257
+ seconds: int = 300,
258
+ index_keys: str | None = "time_msc",
259
+ ) -> pd.DataFrame:
260
+ """Fetch tick data as a DataFrame.
261
+
262
+ Args:
263
+ symbol: Symbol to fetch tick data for.
264
+ seconds: Time range in seconds to fetch ticks around the last tick time.
265
+ index_keys: Optional index keys for the DataFrame.
266
+
267
+ Returns:
268
+ pd.DataFrame: Tick data with time index.
269
+ """
270
+ last_tick_time = self.symbol_info_tick_as_dict(symbol=symbol)["time"]
271
+ return self.copy_ticks_range_as_df(
272
+ symbol=symbol,
273
+ date_from=(last_tick_time - timedelta(seconds=seconds)),
274
+ date_to=(last_tick_time + timedelta(seconds=seconds)),
275
+ flags=self.mt5.COPY_TICKS_ALL,
276
+ index_keys=index_keys,
277
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdmt5
3
- Version: 0.1.1
3
+ Version: 0.1.3
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>
@@ -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=4rT0WgK0JyLMv8XatXur8-NWqG6gh_8XQ-g5sVX9xq0,6987
4
+ pdmt5/trading.py,sha256=FsLC_X_bwBnnQ9l54wPA4OlwD2HlO1RnPvOCnMopNNE,10113
5
5
  pdmt5/utils.py,sha256=Ll5Q3OE5h1A_sZ_qVEnOPGniFlT6_MmHfuu0zqeLdeU,3913
6
- pdmt5-0.1.1.dist-info/METADATA,sha256=q-ucK2453_zDdVKufYI03PmkfRqwt3WcNdTdwu1OPkw,9029
7
- pdmt5-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- pdmt5-0.1.1.dist-info/licenses/LICENSE,sha256=iABrdaUGOBWLYotFupB_PGe8arV5o7rVhn-_vK6P704,1073
9
- pdmt5-0.1.1.dist-info/RECORD,,
6
+ pdmt5-0.1.3.dist-info/METADATA,sha256=UpjES_3YPgMHCpmX4da8ox0OlqJ36nE5B-cYNKvv2A8,9029
7
+ pdmt5-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ pdmt5-0.1.3.dist-info/licenses/LICENSE,sha256=iABrdaUGOBWLYotFupB_PGe8arV5o7rVhn-_vK6P704,1073
9
+ pdmt5-0.1.3.dist-info/RECORD,,
File without changes