mt5cli 0.9.6__tar.gz → 1.0.0__tar.gz
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.
- {mt5cli-0.9.6 → mt5cli-1.0.0}/PKG-INFO +17 -11
- {mt5cli-0.9.6 → mt5cli-1.0.0}/README.md +13 -8
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/history.md +4 -2
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/index.md +3 -5
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/public-contract.md +54 -89
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/sdk.md +2 -1
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/trading.md +6 -5
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/index.md +11 -9
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mkdocs.yml +0 -1
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/__init__.py +1 -155
- mt5cli-1.0.0/mt5cli/contract.py +69 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/exceptions.py +9 -4
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/sdk.py +7 -2
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/trading.py +153 -91
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/utils.py +13 -6
- {mt5cli-0.9.6 → mt5cli-1.0.0}/pyproject.toml +10 -4
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_contracts.py +138 -111
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_history.py +3 -1
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_trading.py +44 -43
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_utils.py +21 -13
- {mt5cli-0.9.6 → mt5cli-1.0.0}/uv.lock +14 -7
- mt5cli-0.9.6/docs/api/storage.md +0 -3
- mt5cli-0.9.6/mt5cli/contract.py +0 -151
- mt5cli-0.9.6/mt5cli/storage.py +0 -49
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.agents/skills/local-qa/SKILL.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.agents/skills/local-qa/scripts/qa.sh +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.agents/skills/mt5cli/SKILL.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.agents/skills/pr-feedback-triage/SKILL.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.claude/agents/codex.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.claude/settings.json +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/FUNDING.yml +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/dependabot.yml +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/renovate.json +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/workflows/ci.yml +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/workflows/claude.yml +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.github/workflows/release.yml +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/.gitignore +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/AGENTS.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/CLAUDE.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/LICENSE +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/cli.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/client.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/converters.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/exceptions.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/schemas.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/docs/api/utils.md +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/__main__.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/cli.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/client.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/converters.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/history.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/retry.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/mt5cli/schemas.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/__init__.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/conftest.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_cli.py +0 -0
- {mt5cli-0.9.6 → mt5cli-1.0.0}/tests/test_sdk.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mt5cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Generic MT5 data and execution infrastructure for Python applications
|
|
5
5
|
Project-URL: Repository, https://github.com/dceoy/mt5cli.git
|
|
6
6
|
Author-email: dceoy <dceoy@users.noreply.github.com>
|
|
@@ -17,9 +17,10 @@ Classifier: Programming Language :: Python :: 3
|
|
|
17
17
|
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
18
18
|
Requires-Python: <3.14,>=3.11
|
|
19
19
|
Requires-Dist: click>=8.1.0
|
|
20
|
-
Requires-Dist: pdmt5>=0.
|
|
21
|
-
Requires-Dist: pyarrow>=19.0.0
|
|
20
|
+
Requires-Dist: pdmt5>=1.0.0
|
|
22
21
|
Requires-Dist: typer>=0.15.0
|
|
22
|
+
Provides-Extra: parquet
|
|
23
|
+
Requires-Dist: pyarrow>=19.0.0; extra == 'parquet'
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
24
25
|
|
|
25
26
|
# mt5cli
|
|
@@ -53,6 +54,12 @@ Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data han
|
|
|
53
54
|
pip install -U mt5cli MetaTrader5
|
|
54
55
|
```
|
|
55
56
|
|
|
57
|
+
Parquet export is not included by default. To enable it, install the `parquet` extra:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install -U "mt5cli[parquet]" MetaTrader5
|
|
61
|
+
```
|
|
62
|
+
|
|
56
63
|
## Python API (downstream packages)
|
|
57
64
|
|
|
58
65
|
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives.
|
|
@@ -62,16 +69,14 @@ from datetime import UTC, datetime
|
|
|
62
69
|
from pathlib import Path
|
|
63
70
|
|
|
64
71
|
from mt5cli import (
|
|
65
|
-
DataKind,
|
|
66
|
-
Dataset,
|
|
67
72
|
MT5Client,
|
|
68
73
|
build_config,
|
|
69
74
|
collect_history,
|
|
70
|
-
export_dataframe,
|
|
71
75
|
mt5_session,
|
|
72
|
-
normalize_dataframe,
|
|
73
76
|
update_history_with_config,
|
|
74
77
|
)
|
|
78
|
+
from mt5cli.schemas import DataKind, normalize_dataframe
|
|
79
|
+
from mt5cli.utils import Dataset, export_dataframe
|
|
75
80
|
|
|
76
81
|
# Persistent session for multiple calls
|
|
77
82
|
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
@@ -107,7 +112,7 @@ update_history_with_config(
|
|
|
107
112
|
)
|
|
108
113
|
```
|
|
109
114
|
|
|
110
|
-
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`).
|
|
115
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Export and storage helpers are in `mt5cli.utils` (`Dataset`, `export_dataframe`) and `mt5cli.history`.
|
|
111
116
|
|
|
112
117
|
`MT5Client.order_send()` is a live execution primitive: it can place real trades on the connected account. mt5cli does not implement strategy logic, signal generation, backtesting, or optimization — downstream applications must gate live execution explicitly.
|
|
113
118
|
|
|
@@ -230,7 +235,8 @@ For automated pipelines, use the importable incremental API instead of re-fetchi
|
|
|
230
235
|
|
|
231
236
|
```python
|
|
232
237
|
from pdmt5 import Mt5Config, Mt5DataClient
|
|
233
|
-
from mt5cli import
|
|
238
|
+
from mt5cli import update_history, update_history_with_config
|
|
239
|
+
from mt5cli.utils import Dataset
|
|
234
240
|
|
|
235
241
|
# Reuse an already-connected pdmt5 client (does not open/close MT5)
|
|
236
242
|
client = Mt5DataClient(config=Mt5Config(login=12345))
|
|
@@ -265,7 +271,7 @@ update_history_with_config(
|
|
|
265
271
|
- **Rate view resolution**: use `resolve_rate_view_name()` / `resolve_rate_view_names()` to map symbols and granularities to existing SQLite compatibility views without creating databases. Both accept `None` (or a missing path) and return deterministic default names unless `require_existing=True`.
|
|
266
272
|
- **Rate view loading**: use `load_rate_data()` / `load_rate_data_from_connection()` to load a SQLite rate table or view into a `DatetimeIndex` DataFrame.
|
|
267
273
|
- **Multi-series rate loading**: use `build_rate_targets()` to build neutral `RateTarget(symbol, timeframe)` pairs, `resolve_rate_tables()` to map them to table/view names (pass `require_existing=True` for strict resolution), and `load_rate_series_from_sqlite()` to load them into a mapping keyed by `(symbol, integer timeframe)`. The loader requires existing managed views unless `explicit_tables` is supplied, and rejects duplicate `(symbol, timeframe)` targets.
|
|
268
|
-
- **Multi-account latest rates**: use `collect_latest_rates_for_accounts()` with `AccountSpec` to read the latest bars for several account groups, merged into a `(symbol, integer timeframe)` mapping. For long-running pollers, `collect_latest_rates_for_accounts_with_retries()` adds bounded exponential backoff that retries only
|
|
274
|
+
- **Multi-account latest rates**: use `collect_latest_rates_for_accounts()` with `AccountSpec` to read the latest bars for several account groups, merged into a `(symbol, integer timeframe)` mapping. For long-running pollers, `collect_latest_rates_for_accounts_with_retries()` adds bounded exponential backoff that retries only recoverable MT5 errors and re-raises once `retry_count` is exhausted.
|
|
269
275
|
- **Latest closed bars**: use `collect_latest_closed_rates_for_accounts()` when downstream logic must exclude the still-forming current bar. It fetches `count + 1` bars at `start_pos=0`, drops the last row with `drop_forming_rate_bar()`, and validates each series is non-empty. `collect_latest_closed_rates_by_granularity()` returns the same data keyed by `(symbol, granularity_name)` such as `("EURUSD", "M1")`.
|
|
270
276
|
|
|
271
277
|
```python
|
|
@@ -282,7 +288,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
|
|
|
282
288
|
|
|
283
289
|
- **Credential resolution**: use `resolve_account_spec()` / `resolve_account_specs()` to merge explicit override values over `AccountSpec` fields and expand `${ENV_VAR}` placeholders (via `substitute_env_placeholders()`), raising `ValueError` for missing variables. This keeps secrets out of plan/config files without coupling to any strategy code. For config dicts or nested structures loaded from YAML/TOML, use `substitute_mapping_values(data, keys={"login", "password"})` to expand placeholders only for caller-specified keys — key names are never hard-coded in mt5cli.
|
|
284
290
|
- **Throttled history updates**: use `ThrottledHistoryUpdater` to wrap `update_history()` with a minimum `interval_seconds` between successful runs (monotonic clock). Call `should_update()` / `update(client, symbols)` from an application loop; errors propagate by default, or pass `suppress_errors=True` to swallow recoverable `Mt5*Error`, `sqlite3.Error`, `ValueError`, `OSError`, and MT5 client capability errors for history API methods without advancing the throttle (other `AttributeError` / `TypeError` values always propagate). Pass `update_backend` to inject a custom history update callable (same keyword arguments as `update_history`) instead of monkey-patching `mt5cli.sdk.update_history`.
|
|
285
|
-
- **Trading session helpers**: use `mt5_trading_session()` for a trading-capable
|
|
291
|
+
- **Trading session helpers**: use `mt5_trading_session()` for a trading-capable client that initializes/logs in via `Mt5Config.path` and always shuts down safely. Pair with `detect_position_side()`, `calculate_margin_and_volume()`, and `determine_order_limits()` for generic position and sizing utilities. Keep read-only collection on `mt5_session()` / `MT5Client`.
|
|
286
292
|
- **Granularity-keyed rate loading**: `load_rate_series_by_granularity()` builds targets with `build_rate_targets()`, loads them with `load_rate_series_from_sqlite()`, and returns a mapping keyed by `(symbol | None, granularity_name)` such as `("EURUSD", "M1")` to reduce downstream boilerplate.
|
|
287
293
|
- **MT5 session helper**: use the `mt5_session()` context manager to attach to (or, when `Mt5Config.path` is set, launch) an MT5 terminal, log in, and yield a connected `MT5Client` that shuts down on exit.
|
|
288
294
|
- **SQLite export helpers**: use `export_dataframe_to_sqlite()` for append mode, optional index export, and post-write deduplication by key columns.
|
|
@@ -29,6 +29,12 @@ Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data han
|
|
|
29
29
|
pip install -U mt5cli MetaTrader5
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
Parquet export is not included by default. To enable it, install the `parquet` extra:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install -U "mt5cli[parquet]" MetaTrader5
|
|
36
|
+
```
|
|
37
|
+
|
|
32
38
|
## Python API (downstream packages)
|
|
33
39
|
|
|
34
40
|
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives.
|
|
@@ -38,16 +44,14 @@ from datetime import UTC, datetime
|
|
|
38
44
|
from pathlib import Path
|
|
39
45
|
|
|
40
46
|
from mt5cli import (
|
|
41
|
-
DataKind,
|
|
42
|
-
Dataset,
|
|
43
47
|
MT5Client,
|
|
44
48
|
build_config,
|
|
45
49
|
collect_history,
|
|
46
|
-
export_dataframe,
|
|
47
50
|
mt5_session,
|
|
48
|
-
normalize_dataframe,
|
|
49
51
|
update_history_with_config,
|
|
50
52
|
)
|
|
53
|
+
from mt5cli.schemas import DataKind, normalize_dataframe
|
|
54
|
+
from mt5cli.utils import Dataset, export_dataframe
|
|
51
55
|
|
|
52
56
|
# Persistent session for multiple calls
|
|
53
57
|
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
@@ -83,7 +87,7 @@ update_history_with_config(
|
|
|
83
87
|
)
|
|
84
88
|
```
|
|
85
89
|
|
|
86
|
-
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`).
|
|
90
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Export and storage helpers are in `mt5cli.utils` (`Dataset`, `export_dataframe`) and `mt5cli.history`.
|
|
87
91
|
|
|
88
92
|
`MT5Client.order_send()` is a live execution primitive: it can place real trades on the connected account. mt5cli does not implement strategy logic, signal generation, backtesting, or optimization — downstream applications must gate live execution explicitly.
|
|
89
93
|
|
|
@@ -206,7 +210,8 @@ For automated pipelines, use the importable incremental API instead of re-fetchi
|
|
|
206
210
|
|
|
207
211
|
```python
|
|
208
212
|
from pdmt5 import Mt5Config, Mt5DataClient
|
|
209
|
-
from mt5cli import
|
|
213
|
+
from mt5cli import update_history, update_history_with_config
|
|
214
|
+
from mt5cli.utils import Dataset
|
|
210
215
|
|
|
211
216
|
# Reuse an already-connected pdmt5 client (does not open/close MT5)
|
|
212
217
|
client = Mt5DataClient(config=Mt5Config(login=12345))
|
|
@@ -241,7 +246,7 @@ update_history_with_config(
|
|
|
241
246
|
- **Rate view resolution**: use `resolve_rate_view_name()` / `resolve_rate_view_names()` to map symbols and granularities to existing SQLite compatibility views without creating databases. Both accept `None` (or a missing path) and return deterministic default names unless `require_existing=True`.
|
|
242
247
|
- **Rate view loading**: use `load_rate_data()` / `load_rate_data_from_connection()` to load a SQLite rate table or view into a `DatetimeIndex` DataFrame.
|
|
243
248
|
- **Multi-series rate loading**: use `build_rate_targets()` to build neutral `RateTarget(symbol, timeframe)` pairs, `resolve_rate_tables()` to map them to table/view names (pass `require_existing=True` for strict resolution), and `load_rate_series_from_sqlite()` to load them into a mapping keyed by `(symbol, integer timeframe)`. The loader requires existing managed views unless `explicit_tables` is supplied, and rejects duplicate `(symbol, timeframe)` targets.
|
|
244
|
-
- **Multi-account latest rates**: use `collect_latest_rates_for_accounts()` with `AccountSpec` to read the latest bars for several account groups, merged into a `(symbol, integer timeframe)` mapping. For long-running pollers, `collect_latest_rates_for_accounts_with_retries()` adds bounded exponential backoff that retries only
|
|
249
|
+
- **Multi-account latest rates**: use `collect_latest_rates_for_accounts()` with `AccountSpec` to read the latest bars for several account groups, merged into a `(symbol, integer timeframe)` mapping. For long-running pollers, `collect_latest_rates_for_accounts_with_retries()` adds bounded exponential backoff that retries only recoverable MT5 errors and re-raises once `retry_count` is exhausted.
|
|
245
250
|
- **Latest closed bars**: use `collect_latest_closed_rates_for_accounts()` when downstream logic must exclude the still-forming current bar. It fetches `count + 1` bars at `start_pos=0`, drops the last row with `drop_forming_rate_bar()`, and validates each series is non-empty. `collect_latest_closed_rates_by_granularity()` returns the same data keyed by `(symbol, granularity_name)` such as `("EURUSD", "M1")`.
|
|
246
251
|
|
|
247
252
|
```python
|
|
@@ -258,7 +263,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
|
|
|
258
263
|
|
|
259
264
|
- **Credential resolution**: use `resolve_account_spec()` / `resolve_account_specs()` to merge explicit override values over `AccountSpec` fields and expand `${ENV_VAR}` placeholders (via `substitute_env_placeholders()`), raising `ValueError` for missing variables. This keeps secrets out of plan/config files without coupling to any strategy code. For config dicts or nested structures loaded from YAML/TOML, use `substitute_mapping_values(data, keys={"login", "password"})` to expand placeholders only for caller-specified keys — key names are never hard-coded in mt5cli.
|
|
260
265
|
- **Throttled history updates**: use `ThrottledHistoryUpdater` to wrap `update_history()` with a minimum `interval_seconds` between successful runs (monotonic clock). Call `should_update()` / `update(client, symbols)` from an application loop; errors propagate by default, or pass `suppress_errors=True` to swallow recoverable `Mt5*Error`, `sqlite3.Error`, `ValueError`, `OSError`, and MT5 client capability errors for history API methods without advancing the throttle (other `AttributeError` / `TypeError` values always propagate). Pass `update_backend` to inject a custom history update callable (same keyword arguments as `update_history`) instead of monkey-patching `mt5cli.sdk.update_history`.
|
|
261
|
-
- **Trading session helpers**: use `mt5_trading_session()` for a trading-capable
|
|
266
|
+
- **Trading session helpers**: use `mt5_trading_session()` for a trading-capable client that initializes/logs in via `Mt5Config.path` and always shuts down safely. Pair with `detect_position_side()`, `calculate_margin_and_volume()`, and `determine_order_limits()` for generic position and sizing utilities. Keep read-only collection on `mt5_session()` / `MT5Client`.
|
|
262
267
|
- **Granularity-keyed rate loading**: `load_rate_series_by_granularity()` builds targets with `build_rate_targets()`, loads them with `load_rate_series_from_sqlite()`, and returns a mapping keyed by `(symbol | None, granularity_name)` such as `("EURUSD", "M1")` to reduce downstream boilerplate.
|
|
263
268
|
- **MT5 session helper**: use the `mt5_session()` context manager to attach to (or, when `Mt5Config.path` is set, launch) an MT5 terminal, log in, and yield a connected `MT5Client` that shuts down on exit.
|
|
264
269
|
- **SQLite export helpers**: use `export_dataframe_to_sqlite()` for append mode, optional index export, and post-write deduplication by key columns.
|
|
@@ -182,12 +182,14 @@ targets without hard-coding view names:
|
|
|
182
182
|
from pathlib import Path
|
|
183
183
|
|
|
184
184
|
from mt5cli import (
|
|
185
|
-
load_rate_data,
|
|
186
185
|
load_rate_series_by_granularity,
|
|
187
186
|
load_rate_series_from_sqlite,
|
|
187
|
+
)
|
|
188
|
+
from mt5cli.history import (
|
|
189
|
+
load_rate_data,
|
|
188
190
|
resolve_rate_table_name,
|
|
191
|
+
resolve_rate_view_name,
|
|
189
192
|
)
|
|
190
|
-
from mt5cli.history import resolve_rate_view_name
|
|
191
193
|
|
|
192
194
|
view = resolve_rate_view_name(Path("history.db"), "EURUSD", "M1", require_existing=True)
|
|
193
195
|
rates = load_rate_data(Path("history.db"), view, count=1000)
|
|
@@ -13,7 +13,6 @@ responsibilities.
|
|
|
13
13
|
| [Public API Contract](public-contract.md) | Stable downstream SDK exports, CLI boundary, and out-of-scope items |
|
|
14
14
|
| [Client](client.md) | `MT5Client` session abstraction for data access and order primitives |
|
|
15
15
|
| [Schemas](schemas.md) | Canonical DataFrame contracts and normalization helpers |
|
|
16
|
-
| [Storage](storage.md) | CSV/JSON/Parquet/SQLite export and history collection helpers |
|
|
17
16
|
| [Converters](converters.md) | Symbol, timeframe, timezone, and date-range utilities |
|
|
18
17
|
| [Exceptions](exceptions.md) | Stable mt5cli exception types and MT5 error normalization |
|
|
19
18
|
| [SDK](sdk.md) | Module-level fetch helpers, multi-account collectors, incremental history |
|
|
@@ -30,15 +29,14 @@ flowchart TD
|
|
|
30
29
|
CLI["mt5cli CLI"] --> Client
|
|
31
30
|
Client --> SDK["sdk / pdmt5"]
|
|
32
31
|
Client --> Schemas["schemas"]
|
|
33
|
-
|
|
34
|
-
Storage --> Utils["utils export"]
|
|
32
|
+
History["history SQLite"] --> Utils["utils export"]
|
|
35
33
|
SDK --> PDMT5["pdmt5.Mt5DataClient"]
|
|
36
34
|
```
|
|
37
35
|
|
|
38
36
|
Downstream packages should depend on the package root exports documented in the
|
|
39
37
|
[Public API Contract](public-contract.md) (`MT5Client`,
|
|
40
|
-
`
|
|
41
|
-
|
|
38
|
+
`collect_history`, `load_rate_series_from_sqlite`, etc.) rather than private
|
|
39
|
+
modules. Lower-level helpers are accessible directly from their owning modules.
|
|
42
40
|
|
|
43
41
|
`MT5Client.order_send()` is a live execution primitive that can place real trades. mt5cli exposes minimal execution helpers only; strategy logic, signals, backtests, and optimization remain out of scope and must be implemented downstream with explicit execution gating.
|
|
44
42
|
|
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
# Public API Contract
|
|
2
2
|
|
|
3
|
-
mt5cli is the
|
|
4
|
-
|
|
3
|
+
mt5cli is the canonical operational trading SDK and CLI/batch layer over pdmt5.
|
|
4
|
+
The intended dependency direction is:
|
|
5
5
|
|
|
6
6
|
```text
|
|
7
7
|
downstream app -> mt5cli -> pdmt5 -> MetaTrader 5
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
## Responsibility boundary
|
|
11
|
+
|
|
12
|
+
| Layer | Owns |
|
|
13
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
14
|
+
| **pdmt5** | MT5 core wrapper; DataFrame/dict conversion; canonical MT5 constants and parsers; direct low-level order primitives |
|
|
15
|
+
| **mt5cli** | CLI/batch workflows; SQLite history collection; normalized datasets; closed-bar helpers; small downstream operational SDK; generic broker-facing margin/volume/order orchestration |
|
|
16
|
+
| **downstream** | Strategy logic; signals; risk policy; backtesting; optimization; YAML/application semantics |
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Downstream code should import raw pdmt5 types and constants (such as
|
|
19
|
+
`Mt5Config`, `Mt5RuntimeError`, `TIMEFRAME_MAP`, `COPY_TICKS_MAP`) directly
|
|
20
|
+
from `pdmt5` when needed. mt5cli does not serve as a pass-through compatibility
|
|
21
|
+
namespace for pdmt5. mt5cli's trading helpers type their client parameter against
|
|
22
|
+
an internal protocol backed by `pdmt5.Mt5DataClient`; `Mt5TradingClient` is no
|
|
23
|
+
longer required. `Mt5TradingError` is conditionally imported where still present
|
|
24
|
+
in pdmt5, but mt5cli raises `Mt5OperationError` for all trading-related failures.
|
|
16
25
|
|
|
17
|
-
mt5cli
|
|
26
|
+
Note: the former `mt5cli` re-export `TICK_FLAG_MAP` corresponds to `COPY_TICKS_MAP`
|
|
27
|
+
in pdmt5 — the name changed, it was not simply moved.
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
Downstream packages should import from the package root (`from mt5cli import
|
|
30
|
+
...`). The contract set `STABLE_SDK_EXPORTS` in `mt5cli.contract` enumerates
|
|
31
|
+
every package-root symbol. Lower-level helpers (schema utilities, export
|
|
32
|
+
functions, parser helpers, low-level MT5 wrappers) are available directly from
|
|
33
|
+
their owning modules (`mt5cli.schemas`, `mt5cli.utils`, `mt5cli.converters`,
|
|
34
|
+
`mt5cli.sdk`, etc.) and are not part of the root SDK surface.
|
|
23
35
|
|
|
24
36
|
## Stable downstream SDK API
|
|
25
37
|
|
|
26
|
-
These names are exported from `mt5cli` and
|
|
38
|
+
These names are exported from `mt5cli` and enumerated in
|
|
27
39
|
`mt5cli.STABLE_SDK_EXPORTS` (defined in `mt5cli.contract`).
|
|
28
40
|
|
|
29
41
|
### Session lifecycle and configuration
|
|
@@ -33,23 +45,9 @@ These names are exported from `mt5cli` and covered by the contract in
|
|
|
33
45
|
| `MT5Client` | Read-only data client with optional `order_check` / `order_send` |
|
|
34
46
|
| `build_config` | Build `pdmt5.Mt5Config` from connection fields; `login` accepts `int \| str \| None` — numeric strings are coerced to `int`, blank strings are treated as unset, and `${ENV_VAR}` / `$ENV_NAME` placeholders in string parameters are expanded when `allow_whole_dollar_env=True` |
|
|
35
47
|
| `mt5_session` | Context manager: initialize, login, yield client, shutdown |
|
|
36
|
-
| `create_trading_client`, `mt5_trading_session` | Trading-capable
|
|
48
|
+
| `create_trading_client`, `mt5_trading_session` | Trading-capable MT5 client lifecycle; returns a client supporting order execution and account management |
|
|
37
49
|
| `AccountSpec` | Generic account group: symbols plus optional credentials |
|
|
38
50
|
| `resolve_account_spec`, `resolve_account_specs` | Merge overrides and expand `${ENV_VAR}` placeholders; opt-in `allow_whole_dollar_env` for bare `$NAME` |
|
|
39
|
-
| `substitute_env_placeholders` | Replace `${NAME}` substrings from the environment; opt-in `allow_whole_dollar_env` for whole-value `$NAME` |
|
|
40
|
-
| `substitute_mapping_values` | Recursively traverse a dict/list/scalar structure and substitute `${ENV_VAR}` placeholders for caller-selected mapping keys only; optionally normalise blank strings to `None` for a separate caller-selected key set; does not hard-code any application-specific key names |
|
|
41
|
-
|
|
42
|
-
Credential resolution is generic: any environment variable name may appear inside
|
|
43
|
-
`${...}`. mt5cli does not hard-code application-specific keys such as
|
|
44
|
-
`mt5_login` or `mt5_exe`.
|
|
45
|
-
|
|
46
|
-
Pass `allow_whole_dollar_env=True` to `substitute_env_placeholders()`,
|
|
47
|
-
`substitute_mapping_values()`, `resolve_account_spec()`, `resolve_account_specs()`,
|
|
48
|
-
and `build_config()` to additionally expand strings whose entire value is a bare
|
|
49
|
-
`$ENV_NAME` identifier.
|
|
50
|
-
Partial strings such as `"plan$pass"`, `"abc$ENV"`, or `"$ENV-suffix"` are
|
|
51
|
-
**never** expanded — only an exact `$IDENTIFIER` whole-string match qualifies.
|
|
52
|
-
Default is `False` to preserve backward compatibility.
|
|
53
51
|
|
|
54
52
|
### Closed-bar rate helpers
|
|
55
53
|
|
|
@@ -61,7 +59,7 @@ timestamp normalization in downstream apps.
|
|
|
61
59
|
| ------------------------------------------------ | ------------------------------------------------------------------------------- |
|
|
62
60
|
| `drop_forming_rate_bar` | Remove the last row from chronologically ordered rate data |
|
|
63
61
|
| `fetch_latest_closed_rates` | Single connected client: fetch `count + 1`, drop forming bar |
|
|
64
|
-
| `fetch_latest_closed_rates_for_trading_client` | Closed bars from an active
|
|
62
|
+
| `fetch_latest_closed_rates_for_trading_client` | Closed bars from an active trading client session; returns RangeIndex |
|
|
65
63
|
| `fetch_latest_closed_rates_indexed` | Same as above but returns a UTC `DatetimeIndex` named `"time"` (no time column) |
|
|
66
64
|
| `collect_latest_closed_rates_for_accounts` | Multi-account closed bars with optional retry wrapper |
|
|
67
65
|
| `collect_latest_closed_rates_by_granularity` | Same data keyed by `(symbol, granularity_name)` |
|
|
@@ -69,20 +67,13 @@ timestamp normalization in downstream apps.
|
|
|
69
67
|
|
|
70
68
|
### SQLite history collection and rate loading
|
|
71
69
|
|
|
72
|
-
| Symbol
|
|
73
|
-
|
|
|
74
|
-
| `collect_history`
|
|
75
|
-
| `update_history`, `update_history_with_config`
|
|
76
|
-
| `ThrottledHistoryUpdater`
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `RateTarget`, `build_rate_targets` | Neutral `(symbol, timeframe)` series descriptors |
|
|
80
|
-
| `load_rate_data`, `load_rate_data_from_connection` | Load one table/view into a time-indexed DataFrame |
|
|
81
|
-
| `load_rate_series_from_sqlite`, `load_rate_series_by_granularity` | Load one or many series; fail clearly when managed views are missing |
|
|
82
|
-
|
|
83
|
-
Pass `require_existing=True` to rate view resolution helpers when downstream
|
|
84
|
-
code must fail instead of receiving a best-guess view name. Multi-series loaders
|
|
85
|
-
require existing managed `rate_*__*` views unless `explicit_tables` is supplied.
|
|
70
|
+
| Symbol | Role |
|
|
71
|
+
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `collect_history` | One-shot date-range export into SQLite |
|
|
73
|
+
| `update_history`, `update_history_with_config` | Incremental append from `MAX(time)` cursors |
|
|
74
|
+
| `ThrottledHistoryUpdater` | Minimum interval between successful incremental updates; optional `update_backend` injection |
|
|
75
|
+
| `RateTarget`, `build_rate_targets` | Neutral `(symbol, timeframe)` series descriptors |
|
|
76
|
+
| `load_rate_series_from_sqlite`, `load_rate_series_by_granularity` | Load one or many series; fail clearly when managed views are missing |
|
|
86
77
|
|
|
87
78
|
See [History Collection (SQLite)](history.md) for schema, view naming, and ER
|
|
88
79
|
diagrams.
|
|
@@ -123,7 +114,7 @@ strategy policy.
|
|
|
123
114
|
`MT5Client.order_send()` and CLI `order-send --yes` are live execution paths.
|
|
124
115
|
|
|
125
116
|
Order helpers validate broker stop-level distance in `determine_order_limits()` and
|
|
126
|
-
raise `
|
|
117
|
+
raise `Mt5OperationError` when computed SL/TP prices are too close to the entry
|
|
127
118
|
quote. Validation uses `trade_stops_level * point` from the current quote and
|
|
128
119
|
symbol metadata as a pre-check only; it does not guarantee live order acceptance
|
|
129
120
|
after price movement and does not inspect `trade_freeze_level`. Live
|
|
@@ -133,51 +124,25 @@ sending requests. Failed, malformed, or unknown broker retcodes are fail-closed
|
|
|
133
124
|
and returned as `status="failed"` with normalized `request` / `response` details;
|
|
134
125
|
`dry_run=True` never calls `ensure_symbol_selected()` or `order_send()`.
|
|
135
126
|
|
|
136
|
-
### Errors
|
|
137
|
-
|
|
138
|
-
| Symbol | Role |
|
|
139
|
-
| ------------------------------------------------------------------------------------ | ----------------------------------------------- |
|
|
140
|
-
| `Mt5CliError`, `Mt5ConnectionError`, `Mt5OperationError`, `Mt5SchemaError` | Stable mt5cli exception types |
|
|
141
|
-
| `normalize_mt5_exception`, `call_with_normalized_errors`, `is_recoverable_mt5_error` | Error normalization and retry classification |
|
|
142
|
-
| `Mt5Config`, `Mt5RuntimeError`, `Mt5TradingClient`, `Mt5TradingError` | Re-exported pdmt5 types for adapter convenience |
|
|
143
|
-
|
|
144
|
-
## Secondary public exports
|
|
145
|
-
|
|
146
|
-
These names remain importable from `mt5cli` and are covered by
|
|
147
|
-
`SECONDARY_PUBLIC_EXPORTS`, but they are oriented toward CLI/export/schema
|
|
148
|
-
integrations, parsing, and lower-level MT5 access rather than the stable core
|
|
149
|
-
SDK surface. Prefer the stable symbols above for downstream infrastructure
|
|
150
|
-
adapters.
|
|
151
|
-
|
|
152
|
-
### Read-only MT5 data wrappers
|
|
153
|
-
|
|
154
|
-
Module-level helpers open a transient connection per call. Prefer `mt5_session`
|
|
155
|
-
or `MT5Client` when making many requests in one process.
|
|
127
|
+
### Errors
|
|
156
128
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
| Ticks | `copy_ticks_from`, `copy_ticks_range`, `recent_ticks` |
|
|
161
|
-
| Account / terminal | `account_info`, `terminal_info`, `mt5_version`, `last_error`, `mt5_summary`, `mt5_summary_as_df` |
|
|
162
|
-
| Symbols / market | `symbols`, `symbol_info`, `symbol_info_tick`, `market_book`, `minimum_margins` |
|
|
163
|
-
| Trading state (read) | `orders`, `positions`, `history_orders`, `history_deals`, `recent_history_deals` |
|
|
164
|
-
| Multi-account rates | `collect_latest_rates_for_accounts` |
|
|
129
|
+
| Symbol | Role |
|
|
130
|
+
| -------------------------------------------------------------------------- | ----------------------------- |
|
|
131
|
+
| `Mt5CliError`, `Mt5ConnectionError`, `Mt5OperationError`, `Mt5SchemaError` | Stable mt5cli exception types |
|
|
165
132
|
|
|
166
|
-
|
|
167
|
-
the package root refers to `importlib.metadata.version` (package metadata), not
|
|
168
|
-
the MT5 SDK helper.
|
|
133
|
+
## Module-scoped helpers
|
|
169
134
|
|
|
170
|
-
|
|
135
|
+
Lower-level helpers are available from their owning modules and are not part
|
|
136
|
+
of the package-root stable surface. Import them directly when needed:
|
|
171
137
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
|
|
|
178
|
-
|
|
|
179
|
-
|
|
|
180
|
-
| Trading data shapes | `POSITION_COLUMNS` |
|
|
138
|
+
| Module | Examples |
|
|
139
|
+
| ------------------- | ---------------------------------------------------------------------------------------------- |
|
|
140
|
+
| `mt5cli.history` | `resolve_rate_view_name`, `resolve_rate_tables`, `load_rate_data`, `build_rate_view_name` |
|
|
141
|
+
| `mt5cli.sdk` | `copy_rates_from`, `copy_ticks_from`, `account_info`, `symbols`, `mt5_summary`, `latest_rates` |
|
|
142
|
+
| `mt5cli.schemas` | `DataKind`, `normalize_dataframe`, `validate_schema`, `DEDUP_KEYS` |
|
|
143
|
+
| `mt5cli.utils` | `Dataset`, `IfExists`, `detect_format`, `export_dataframe`, `export_dataframe_to_sqlite` |
|
|
144
|
+
| `mt5cli.converters` | `normalize_symbol`, `ensure_utc`, `parse_date_range`, `granularity_name` |
|
|
145
|
+
| `mt5cli.exceptions` | `normalize_mt5_exception`, `call_with_normalized_errors`, `is_recoverable_mt5_error` |
|
|
181
146
|
|
|
182
147
|
## CLI commands
|
|
183
148
|
|
|
@@ -231,7 +196,7 @@ their own adapter layer.
|
|
|
231
196
|
|
|
232
197
|
## Contract verification
|
|
233
198
|
|
|
234
|
-
`tests/test_contracts.py` asserts that every name in
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
199
|
+
`tests/test_contracts.py` asserts that every name in `STABLE_SDK_EXPORTS` is
|
|
200
|
+
importable from `mt5cli`, that all package-root exports are covered by the
|
|
201
|
+
stable set, and documents key closed-bar, SQLite loading, account-resolution,
|
|
202
|
+
and trading-session behaviors.
|
|
@@ -117,7 +117,8 @@ call it every iteration without over-fetching.
|
|
|
117
117
|
```python
|
|
118
118
|
from pdmt5 import Mt5Config, Mt5DataClient
|
|
119
119
|
|
|
120
|
-
from mt5cli import
|
|
120
|
+
from mt5cli import ThrottledHistoryUpdater
|
|
121
|
+
from mt5cli.utils import Dataset
|
|
121
122
|
|
|
122
123
|
updater = ThrottledHistoryUpdater(
|
|
123
124
|
output="history.db",
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
`create_trading_client()` and `mt5_trading_session()` complement the read-only
|
|
8
8
|
`mt5_session()` helper in `sdk.py`. They return or yield an initialized
|
|
9
|
-
|
|
10
|
-
configured, and `mt5_trading_session()` always
|
|
9
|
+
client supporting order execution and account management, use `Mt5Config.path`
|
|
10
|
+
to launch the terminal when configured, and `mt5_trading_session()` always
|
|
11
|
+
calls `shutdown()` on exit.
|
|
11
12
|
|
|
12
13
|
```python
|
|
13
14
|
from mt5cli import create_trading_client, mt5_trading_session
|
|
@@ -115,19 +116,19 @@ closed = close_open_positions(client, symbols="EURUSD", dry_run=True)
|
|
|
115
116
|
`detect_position_side()` returns `long` for buy-only exposure, `short` for
|
|
116
117
|
sell-only exposure, and `None` for no positions or mixed long/short exposure.
|
|
117
118
|
`calculate_spread_ratio()` uses `(ask - bid) / ((ask + bid) / 2)` and raises
|
|
118
|
-
`
|
|
119
|
+
`Mt5OperationError` when bid or ask is missing or non-positive.
|
|
119
120
|
`normalize_order_volume()` returns `0.0` for invalid constraints or
|
|
120
121
|
sub-minimum requests; check the result before calling `estimate_order_margin()`,
|
|
121
122
|
which requires a positive finite volume. `calculate_positions_margin()` silently
|
|
122
123
|
skips rows with missing symbols, non-positive volumes, non-finite volumes, or
|
|
123
|
-
unsupported position types, but propagates `
|
|
124
|
+
unsupported position types, but propagates `Mt5OperationError` from `estimate_order_margin()` when a valid row
|
|
124
125
|
encounters invalid tick data or margin results from the broker.
|
|
125
126
|
|
|
126
127
|
SL/TP ratios for `determine_order_limits()` must satisfy `0 <= ratio < 1`; `0`
|
|
127
128
|
omits that level. SL/TP prices are rounded with symbol `digits` metadata when
|
|
128
129
|
available. `determine_order_limits()` pre-validates computed SL/TP prices against
|
|
129
130
|
available `trade_stops_level * point` metadata when present; violations raise
|
|
130
|
-
`
|
|
131
|
+
`Mt5OperationError`. This is a planning helper only: it does not guarantee broker
|
|
131
132
|
acceptance because live validation can still depend on price movement, bid/ask
|
|
132
133
|
side, freeze levels, and server-side rules, and it does not validate
|
|
133
134
|
`trade_freeze_level`. When symbol metadata cannot be loaded, protective prices
|
|
@@ -27,6 +27,12 @@ mt5cli provides a stable `MT5Client` Python API, standardized dataset schemas, s
|
|
|
27
27
|
pip install mt5cli
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
Parquet export is not included by default. To enable it, install the `parquet` extra:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install "mt5cli[parquet]"
|
|
34
|
+
```
|
|
35
|
+
|
|
30
36
|
## Python API for downstream packages
|
|
31
37
|
|
|
32
38
|
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives.
|
|
@@ -36,19 +42,15 @@ from datetime import UTC, datetime
|
|
|
36
42
|
from pathlib import Path
|
|
37
43
|
|
|
38
44
|
from mt5cli import (
|
|
39
|
-
DataKind,
|
|
40
|
-
Dataset,
|
|
41
45
|
MT5Client,
|
|
42
46
|
build_config,
|
|
43
47
|
collect_history,
|
|
44
|
-
export_dataframe,
|
|
45
|
-
load_rate_data,
|
|
46
|
-
minimum_margins,
|
|
47
48
|
mt5_session,
|
|
48
|
-
normalize_dataframe,
|
|
49
|
-
recent_ticks,
|
|
50
|
-
resolve_rate_view_name,
|
|
51
49
|
)
|
|
50
|
+
from mt5cli.history import load_rate_data, resolve_rate_view_name
|
|
51
|
+
from mt5cli.schemas import DataKind, normalize_dataframe
|
|
52
|
+
from mt5cli.sdk import minimum_margins, recent_ticks
|
|
53
|
+
from mt5cli.utils import Dataset, export_dataframe
|
|
52
54
|
|
|
53
55
|
# Persistent session for multiple calls
|
|
54
56
|
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
@@ -84,7 +86,7 @@ collect_history(
|
|
|
84
86
|
)
|
|
85
87
|
```
|
|
86
88
|
|
|
87
|
-
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`).
|
|
89
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Export and storage helpers are in `mt5cli.utils` (`Dataset`, `export_dataframe`) and `mt5cli.history`.
|
|
88
90
|
|
|
89
91
|
`MT5Client.order_send()` is a live execution primitive: it can place real trades on the connected account. mt5cli does not implement strategy logic, signal generation, backtesting, or optimization — downstream applications must gate live execution explicitly (the CLI requires `--yes` for `order-send`).
|
|
90
92
|
|