mt5cli 0.9.7__tar.gz → 1.0.1__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.
Files changed (57) hide show
  1. {mt5cli-0.9.7 → mt5cli-1.0.1}/PKG-INFO +9 -10
  2. {mt5cli-0.9.7 → mt5cli-1.0.1}/README.md +7 -8
  3. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/history.md +4 -2
  4. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/index.md +3 -5
  5. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/public-contract.md +54 -89
  6. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/sdk.md +2 -1
  7. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/trading.md +6 -5
  8. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/index.md +30 -22
  9. {mt5cli-0.9.7 → mt5cli-1.0.1}/mkdocs.yml +0 -1
  10. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/__init__.py +1 -155
  11. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/cli.py +41 -30
  12. mt5cli-1.0.1/mt5cli/contract.py +69 -0
  13. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/exceptions.py +9 -4
  14. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/sdk.py +7 -2
  15. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/trading.py +153 -91
  16. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/utils.py +4 -6
  17. {mt5cli-0.9.7 → mt5cli-1.0.1}/pyproject.toml +6 -3
  18. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_cli.py +60 -0
  19. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_contracts.py +116 -111
  20. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_history.py +3 -1
  21. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_trading.py +44 -43
  22. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_utils.py +9 -13
  23. {mt5cli-0.9.7 → mt5cli-1.0.1}/uv.lock +5 -5
  24. mt5cli-0.9.7/docs/api/storage.md +0 -3
  25. mt5cli-0.9.7/mt5cli/contract.py +0 -151
  26. mt5cli-0.9.7/mt5cli/storage.py +0 -49
  27. {mt5cli-0.9.7 → mt5cli-1.0.1}/.agents/skills/local-qa/SKILL.md +0 -0
  28. {mt5cli-0.9.7 → mt5cli-1.0.1}/.agents/skills/local-qa/scripts/qa.sh +0 -0
  29. {mt5cli-0.9.7 → mt5cli-1.0.1}/.agents/skills/mt5cli/SKILL.md +0 -0
  30. {mt5cli-0.9.7 → mt5cli-1.0.1}/.agents/skills/pr-feedback-triage/SKILL.md +0 -0
  31. {mt5cli-0.9.7 → mt5cli-1.0.1}/.claude/agents/codex.md +0 -0
  32. {mt5cli-0.9.7 → mt5cli-1.0.1}/.claude/settings.json +0 -0
  33. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/FUNDING.yml +0 -0
  34. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/dependabot.yml +0 -0
  35. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/renovate.json +0 -0
  36. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/workflows/ci.yml +0 -0
  37. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/workflows/claude.yml +0 -0
  38. {mt5cli-0.9.7 → mt5cli-1.0.1}/.github/workflows/release.yml +0 -0
  39. {mt5cli-0.9.7 → mt5cli-1.0.1}/.gitignore +0 -0
  40. {mt5cli-0.9.7 → mt5cli-1.0.1}/AGENTS.md +0 -0
  41. {mt5cli-0.9.7 → mt5cli-1.0.1}/CLAUDE.md +0 -0
  42. {mt5cli-0.9.7 → mt5cli-1.0.1}/LICENSE +0 -0
  43. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/cli.md +0 -0
  44. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/client.md +0 -0
  45. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/converters.md +0 -0
  46. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/exceptions.md +0 -0
  47. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/schemas.md +0 -0
  48. {mt5cli-0.9.7 → mt5cli-1.0.1}/docs/api/utils.md +0 -0
  49. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/__main__.py +0 -0
  50. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/client.py +0 -0
  51. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/converters.py +0 -0
  52. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/history.py +0 -0
  53. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/retry.py +0 -0
  54. {mt5cli-0.9.7 → mt5cli-1.0.1}/mt5cli/schemas.py +0 -0
  55. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/__init__.py +0 -0
  56. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/conftest.py +0 -0
  57. {mt5cli-0.9.7 → mt5cli-1.0.1}/tests/test_sdk.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mt5cli
3
- Version: 0.9.7
3
+ Version: 1.0.1
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,7 +17,7 @@ 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.3.0
20
+ Requires-Dist: pdmt5>=1.0.0
21
21
  Requires-Dist: typer>=0.15.0
22
22
  Provides-Extra: parquet
23
23
  Requires-Dist: pyarrow>=19.0.0; extra == 'parquet'
@@ -69,16 +69,14 @@ from datetime import UTC, datetime
69
69
  from pathlib import Path
70
70
 
71
71
  from mt5cli import (
72
- DataKind,
73
- Dataset,
74
72
  MT5Client,
75
73
  build_config,
76
74
  collect_history,
77
- export_dataframe,
78
75
  mt5_session,
79
- normalize_dataframe,
80
76
  update_history_with_config,
81
77
  )
78
+ from mt5cli.schemas import DataKind, normalize_dataframe
79
+ from mt5cli.utils import Dataset, export_dataframe
82
80
 
83
81
  # Persistent session for multiple calls
84
82
  with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
@@ -114,7 +112,7 @@ update_history_with_config(
114
112
  )
115
113
  ```
116
114
 
117
- Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
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`.
118
116
 
119
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.
120
118
 
@@ -237,7 +235,8 @@ For automated pipelines, use the importable incremental API instead of re-fetchi
237
235
 
238
236
  ```python
239
237
  from pdmt5 import Mt5Config, Mt5DataClient
240
- from mt5cli import Dataset, update_history, update_history_with_config
238
+ from mt5cli import update_history, update_history_with_config
239
+ from mt5cli.utils import Dataset
241
240
 
242
241
  # Reuse an already-connected pdmt5 client (does not open/close MT5)
243
242
  client = Mt5DataClient(config=Mt5Config(login=12345))
@@ -272,7 +271,7 @@ update_history_with_config(
272
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`.
273
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.
274
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.
275
- - **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 `pdmt5.Mt5TradingError` / `pdmt5.Mt5RuntimeError` and re-raises once `retry_count` is exhausted.
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.
276
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")`.
277
276
 
278
277
  ```python
@@ -289,7 +288,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
289
288
 
290
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.
291
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`.
292
- - **Trading session helpers**: use `mt5_trading_session()` for a trading-capable `pdmt5.Mt5TradingClient` 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`.
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`.
293
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.
294
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.
295
294
  - **SQLite export helpers**: use `export_dataframe_to_sqlite()` for append mode, optional index export, and post-write deduplication by key columns.
@@ -44,16 +44,14 @@ from datetime import UTC, datetime
44
44
  from pathlib import Path
45
45
 
46
46
  from mt5cli import (
47
- DataKind,
48
- Dataset,
49
47
  MT5Client,
50
48
  build_config,
51
49
  collect_history,
52
- export_dataframe,
53
50
  mt5_session,
54
- normalize_dataframe,
55
51
  update_history_with_config,
56
52
  )
53
+ from mt5cli.schemas import DataKind, normalize_dataframe
54
+ from mt5cli.utils import Dataset, export_dataframe
57
55
 
58
56
  # Persistent session for multiple calls
59
57
  with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
@@ -89,7 +87,7 @@ update_history_with_config(
89
87
  )
90
88
  ```
91
89
 
92
- Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
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`.
93
91
 
94
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.
95
93
 
@@ -212,7 +210,8 @@ For automated pipelines, use the importable incremental API instead of re-fetchi
212
210
 
213
211
  ```python
214
212
  from pdmt5 import Mt5Config, Mt5DataClient
215
- from mt5cli import Dataset, update_history, update_history_with_config
213
+ from mt5cli import update_history, update_history_with_config
214
+ from mt5cli.utils import Dataset
216
215
 
217
216
  # Reuse an already-connected pdmt5 client (does not open/close MT5)
218
217
  client = Mt5DataClient(config=Mt5Config(login=12345))
@@ -247,7 +246,7 @@ update_history_with_config(
247
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`.
248
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.
249
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.
250
- - **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 `pdmt5.Mt5TradingError` / `pdmt5.Mt5RuntimeError` and re-raises once `retry_count` is exhausted.
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.
251
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")`.
252
251
 
253
252
  ```python
@@ -264,7 +263,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
264
263
 
265
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.
266
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`.
267
- - **Trading session helpers**: use `mt5_trading_session()` for a trading-capable `pdmt5.Mt5TradingClient` 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`.
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`.
268
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.
269
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.
270
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
- Storage["storage"] --> History["history SQLite"]
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
- `DataKind`, `normalize_dataframe`, `collect_history`, `load_rate_data`,
41
- `resolve_rate_view_name`, etc.) rather than private modules.
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 generic MT5 data and execution infrastructure layer for downstream
4
- Python applications. The intended dependency direction is:
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
- Downstream packages should import from the package root (`from mt5cli import
11
- ...`) and use the public tier sets in `mt5cli.contract` to distinguish API
12
- stability. CLI commands mirror the same behavior but are not importable Python
13
- APIs.
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
- ## Public API tiers
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 classifies package-root imports by intended downstream use:
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
- | Tier | Contract set | Meaning |
20
- | ---------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
21
- | Stable core | `STABLE_SDK_EXPORTS` | Preferred SDK surface for downstream MT5 infrastructure adapters. Changes require a deliberate compatibility path. |
22
- | Secondary public | `SECONDARY_PUBLIC_EXPORTS` | Public helpers for CLI/export/schema integrations and lower-level MT5 wrappers. Importable, but less central to the downstream trading SDK. |
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 covered by the contract in
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 `pdmt5.Mt5TradingClient` lifecycle |
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 `Mt5TradingClient` session; returns RangeIndex |
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 | Role |
73
- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
74
- | `collect_history` | One-shot date-range export into SQLite |
75
- | `update_history`, `update_history_with_config` | Incremental append from `MAX(time)` cursors |
76
- | `ThrottledHistoryUpdater` | Minimum interval between successful incremental updates; optional `update_backend` injection |
77
- | `resolve_history_datasets`, `resolve_history_timeframes`, `resolve_history_tick_flags` | History pipeline configuration |
78
- | `build_rate_view_name`, `resolve_rate_table_name`, `resolve_rate_view_name`, `resolve_rate_view_names`, `resolve_rate_tables` | Map symbols/timeframes to mt5cli-managed table or view names |
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 `Mt5TradingError` when computed SL/TP prices are too close to the entry
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 and MT5 type re-exports
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
- | Area | Symbols |
158
- | -------------------- | ---------------------------------------------------------------------------------------------------- |
159
- | Rates | `copy_rates_from`, `copy_rates_from_pos`, `copy_rates_range`, `latest_rates`, `collect_latest_rates` |
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
- Use `mt5_version` for MetaTrader 5 terminal version data. The name `version` at
167
- the package root refers to `importlib.metadata.version` (package metadata), not
168
- the MT5 SDK helper.
133
+ ## Module-scoped helpers
169
134
 
170
- ### Schema, export, and parser helpers
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
- | Area | Symbols |
173
- | -------------------- | ------------------------------------------------------------------------------------------------------------- |
174
- | Dataset contracts | `DataKind`, `Dataset`, `IfExists`, `DEDUP_KEYS`, `REQUIRED_COLUMNS`, `TIME_COLUMNS`, `KNOWN_MT5_TIME_COLUMNS` |
175
- | Schema normalization | `normalize_dataframe`, `normalize_time_columns`, `schema_columns`, `validate_schema` |
176
- | Export helpers | `detect_format`, `export_dataframe`, `export_dataframe_to_sqlite` |
177
- | Symbol parsing | `normalize_symbol`, `normalize_symbols` |
178
- | Time parsing | `ensure_utc`, `parse_date_range`, `parse_datetime`, `recent_window` |
179
- | MT5 parsing maps | `granularity_name`, `parse_tick_flags`, `parse_timeframe`, `TICK_FLAG_MAP`, `TIMEFRAME_MAP` |
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 the stable and secondary
235
- tier sets is importable from `mt5cli`, documents key closed-bar, rate-view,
236
- SQLite loading, account-resolution, and trading-session behaviors, and keeps the
237
- tier sets aligned with `__all__`.
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 Dataset, ThrottledHistoryUpdater
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
- `pdmt5.Mt5TradingClient`, use `Mt5Config.path` to launch the terminal when
10
- configured, and `mt5_trading_session()` always calls `shutdown()` on exit.
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
- `Mt5TradingError` when bid or ask is missing or non-positive.
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 `Mt5TradingError` from `estimate_order_margin()` when a valid row
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
- `Mt5TradingError`. This is a planning helper only: it does not guarantee broker
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
@@ -42,19 +42,15 @@ from datetime import UTC, datetime
42
42
  from pathlib import Path
43
43
 
44
44
  from mt5cli import (
45
- DataKind,
46
- Dataset,
47
45
  MT5Client,
48
46
  build_config,
49
47
  collect_history,
50
- export_dataframe,
51
- load_rate_data,
52
- minimum_margins,
53
48
  mt5_session,
54
- normalize_dataframe,
55
- recent_ticks,
56
- resolve_rate_view_name,
57
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
58
54
 
59
55
  # Persistent session for multiple calls
60
56
  with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
@@ -90,7 +86,7 @@ collect_history(
90
86
  )
91
87
  ```
92
88
 
93
- Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
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`.
94
90
 
95
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`).
96
92
 
@@ -151,20 +147,32 @@ mt5cli --login 12345 --password mypass --server MyBroker-Demo \
151
147
  | `minimum-margins` | Export minimum-volume margin summary |
152
148
  | `market-book` | Export market depth (order book) |
153
149
 
154
- ### Trading
150
+ ### Trading State
155
151
 
156
- | Command | Description |
157
- | ---------------------- | ----------------------------------------------------------- |
158
- | `orders` | Export active orders |
159
- | `positions` | Export open positions |
160
- | `history-orders` | Export historical orders |
161
- | `history-deals` | Export historical deals |
162
- | `recent-history-deals` | Export historical deals from a trailing window |
163
- | `mt5-summary` | Export terminal/account status summary |
164
- | `order-check` | Check funds sufficiency for a trade request |
165
- | `order-send` | Send a trade request to the trade server (`--yes` required) |
152
+ | Command | Description |
153
+ | ---------------------- | --------------------------------------------------------------------- |
154
+ | `orders` | Export active orders |
155
+ | `positions` | Export open positions |
156
+ | `history-orders` | Export historical orders |
157
+ | `history-deals` | Export historical deals |
158
+ | `recent-history-deals` | Export historical deals from a trailing window |
159
+ | `mt5-summary` | Export terminal/account status summary |
160
+ | `order-check` | Check funds sufficiency for a trade request (read-only, no `--yes`) |
166
161
 
167
- Use `order-check` to validate a request payload before running `order-send --yes`.
162
+ ### Execution (live / mutating)
163
+
164
+ These commands send requests to the live trade server and can place or close
165
+ real trades. Both require `--yes` for live execution.
166
+
167
+ | Command | Description |
168
+ | ----------------- | ---------------------------------------------------------------------------------------------------- |
169
+ | `order-send` | Send a **raw** trade request directly to MT5 (`--yes` required; expert path — no extra validation) |
170
+ | `close-positions` | Close open positions by `--symbol` or `--ticket` (`--yes` required for live; `--dry-run` to preview) |
171
+
172
+ Use `order-check` (Trading State) to validate funds before running `order-send --yes`.
173
+ `close-positions` is the safer high-level alternative that builds correct close
174
+ requests automatically. `order-send` is the expert raw path — downstream
175
+ applications should prefer dedicated closing helpers or their own risk controls.
168
176
 
169
177
  ### Bulk Collection
170
178
 
@@ -221,7 +229,7 @@ See the [History schema diagram](api/history.md#entity-relationship-diagram) for
221
229
 
222
230
  Browse the API documentation for detailed module information:
223
231
 
224
- - [CLI Module](api/cli.md) - CLI application with export commands
232
+ - [CLI Module](api/cli.md) - CLI application with data export and execution commands
225
233
  - [SDK Module](api/sdk.md) - Programmatic read-only data collection API
226
234
  - [Utils Module](api/utils.md) - Constants, parameter types, parsers, and export utilities
227
235
 
@@ -59,7 +59,6 @@ nav:
59
59
  - Public API Contract: api/public-contract.md
60
60
  - Client: api/client.md
61
61
  - Schemas: api/schemas.md
62
- - Storage: api/storage.md
63
62
  - Converters: api/converters.md
64
63
  - Exceptions: api/exceptions.md
65
64
  - CLI: api/cli.md