mt5cli 0.7.1__tar.gz → 0.7.2__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.7.1 → mt5cli-0.7.2}/PKG-INFO +65 -7
- {mt5cli-0.7.1 → mt5cli-0.7.2}/README.md +63 -5
- mt5cli-0.7.2/docs/api/client.md +3 -0
- mt5cli-0.7.2/docs/api/converters.md +3 -0
- mt5cli-0.7.2/docs/api/exceptions.md +3 -0
- mt5cli-0.7.2/docs/api/index.md +53 -0
- mt5cli-0.7.2/docs/api/schemas.md +3 -0
- mt5cli-0.7.2/docs/api/storage.md +3 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/index.md +35 -33
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mkdocs.yml +6 -1
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/__init__.py +60 -8
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/cli.py +6 -21
- mt5cli-0.7.2/mt5cli/client.py +88 -0
- mt5cli-0.7.2/mt5cli/converters.py +162 -0
- mt5cli-0.7.2/mt5cli/exceptions.py +90 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/history.py +5 -4
- mt5cli-0.7.2/mt5cli/retry.py +64 -0
- mt5cli-0.7.2/mt5cli/schemas.py +291 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/sdk.py +18 -21
- mt5cli-0.7.2/mt5cli/storage.py +49 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/pyproject.toml +2 -2
- mt5cli-0.7.2/tests/test_contracts.py +512 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/test_sdk.py +3 -3
- {mt5cli-0.7.1 → mt5cli-0.7.2}/uv.lock +1 -1
- mt5cli-0.7.1/docs/api/index.md +0 -125
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.agents/skills/local-qa/SKILL.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.agents/skills/local-qa/scripts/qa.sh +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.agents/skills/mt5cli/SKILL.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.claude/agents/codex.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.claude/settings.json +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/FUNDING.yml +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/dependabot.yml +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/renovate.json +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/workflows/ci.yml +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/workflows/claude.yml +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.github/workflows/release.yml +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/.gitignore +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/AGENTS.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/CLAUDE.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/LICENSE +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/api/cli.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/api/history.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/api/sdk.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/api/trading.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/docs/api/utils.md +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/__main__.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/trading.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/mt5cli/utils.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/__init__.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/conftest.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/test_cli.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/test_history.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/test_trading.py +0 -0
- {mt5cli-0.7.1 → mt5cli-0.7.2}/tests/test_utils.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mt5cli
|
|
3
|
-
Version: 0.7.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.7.2
|
|
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>
|
|
7
7
|
Maintainer-email: dceoy <dceoy@users.noreply.github.com>
|
|
@@ -26,14 +26,14 @@ Description-Content-Type: text/markdown
|
|
|
26
26
|
|
|
27
27
|
[](https://github.com/dceoy/mt5cli/actions/workflows/ci.yml)
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Generic MT5 data and execution infrastructure for Python applications. Export from the CLI or import a small, stable Python API in downstream packages.
|
|
30
30
|
|
|
31
31
|
Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data handler for MetaTrader 5.
|
|
32
32
|
|
|
33
33
|
## Architecture
|
|
34
34
|
|
|
35
35
|
- **pdmt5** — canonical MT5 client, DataFrame/trading primitives, and MT5 constant parsing (`TIMEFRAME_*`, `COPY_TICKS_*`, order types).
|
|
36
|
-
- **mt5cli** —
|
|
36
|
+
- **mt5cli** — public `MT5Client` API, standardized dataset schemas, storage helpers, CLI commands, and SQLite history collection built on pdmt5.
|
|
37
37
|
- **mt5api** — sibling HTTP adapter for remote MT5 access; not a dependency of mt5cli.
|
|
38
38
|
|
|
39
39
|
## Features
|
|
@@ -51,7 +51,65 @@ Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data han
|
|
|
51
51
|
pip install -U mt5cli MetaTrader5
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## Python API (downstream packages)
|
|
55
|
+
|
|
56
|
+
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives. `Mt5CliClient` remains available as a backward-compatible alias.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from datetime import UTC, datetime
|
|
60
|
+
from pathlib import Path
|
|
61
|
+
|
|
62
|
+
from mt5cli import (
|
|
63
|
+
DataKind,
|
|
64
|
+
Dataset,
|
|
65
|
+
MT5Client,
|
|
66
|
+
build_config,
|
|
67
|
+
collect_history,
|
|
68
|
+
export_dataframe,
|
|
69
|
+
mt5_session,
|
|
70
|
+
normalize_dataframe,
|
|
71
|
+
update_history_with_config,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Persistent session for multiple calls
|
|
75
|
+
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
76
|
+
rates = client.copy_rates_range(
|
|
77
|
+
"EURUSD",
|
|
78
|
+
timeframe="H1",
|
|
79
|
+
date_from="2024-01-01",
|
|
80
|
+
date_to="2024-02-01",
|
|
81
|
+
)
|
|
82
|
+
positions = client.positions()
|
|
83
|
+
check = client.order_check({"action": 1, "symbol": "EURUSD", "volume": 0.1})
|
|
84
|
+
|
|
85
|
+
# Normalize MT5 frames to the public schema contract before storage
|
|
86
|
+
closed_rates = normalize_dataframe(
|
|
87
|
+
rates, DataKind.rates, symbol="EURUSD", timeframe="H1"
|
|
88
|
+
)
|
|
89
|
+
export_dataframe(closed_rates, Path("rates.csv"), "csv")
|
|
90
|
+
|
|
91
|
+
# Bulk SQLite history (same behavior as collect-history CLI command)
|
|
92
|
+
collect_history(
|
|
93
|
+
Path("history.db"),
|
|
94
|
+
symbols=["EURUSD"],
|
|
95
|
+
date_from=datetime(2024, 1, 1, tzinfo=UTC),
|
|
96
|
+
date_to=datetime(2024, 2, 1, tzinfo=UTC),
|
|
97
|
+
datasets={Dataset.rates, Dataset.history_deals},
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Incremental append for automated pipelines
|
|
101
|
+
update_history_with_config(
|
|
102
|
+
output="history.db",
|
|
103
|
+
symbols=["EURUSD"],
|
|
104
|
+
config=build_config(login=12345),
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
|
|
109
|
+
|
|
110
|
+
`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.
|
|
111
|
+
|
|
112
|
+
## CLI usage
|
|
55
113
|
|
|
56
114
|
```bash
|
|
57
115
|
# Export account information to CSV
|
|
@@ -185,7 +243,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
|
|
|
185
243
|
- **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).
|
|
186
244
|
- **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. The read-only `mt5_session()` / `Mt5CliClient` SDK is unchanged.
|
|
187
245
|
- **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.
|
|
188
|
-
- **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 `
|
|
246
|
+
- **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.
|
|
189
247
|
- **SQLite export helpers**: use `export_dataframe_to_sqlite()` for append mode, optional index export, and post-write deduplication by key columns.
|
|
190
248
|
- **Recent ticks and margins**: `recent_ticks()` and `minimum_margins()` SDK helpers (and matching CLI commands) cover common downstream read-only queries.
|
|
191
249
|
|
|
@@ -250,7 +308,7 @@ finally:
|
|
|
250
308
|
client.shutdown()
|
|
251
309
|
```
|
|
252
310
|
|
|
253
|
-
Read-only collectors can keep using `mt5_session()` and `Mt5CliClient` without changes.
|
|
311
|
+
Read-only collectors can keep using `mt5_session()` and `MT5Client` (or the `Mt5CliClient` alias) without changes.
|
|
254
312
|
|
|
255
313
|
## Development
|
|
256
314
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/dceoy/mt5cli/actions/workflows/ci.yml)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Generic MT5 data and execution infrastructure for Python applications. Export from the CLI or import a small, stable Python API in downstream packages.
|
|
6
6
|
|
|
7
7
|
Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data handler for MetaTrader 5.
|
|
8
8
|
|
|
9
9
|
## Architecture
|
|
10
10
|
|
|
11
11
|
- **pdmt5** — canonical MT5 client, DataFrame/trading primitives, and MT5 constant parsing (`TIMEFRAME_*`, `COPY_TICKS_*`, order types).
|
|
12
|
-
- **mt5cli** —
|
|
12
|
+
- **mt5cli** — public `MT5Client` API, standardized dataset schemas, storage helpers, CLI commands, and SQLite history collection built on pdmt5.
|
|
13
13
|
- **mt5api** — sibling HTTP adapter for remote MT5 access; not a dependency of mt5cli.
|
|
14
14
|
|
|
15
15
|
## Features
|
|
@@ -27,7 +27,65 @@ Built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data han
|
|
|
27
27
|
pip install -U mt5cli MetaTrader5
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Python API (downstream packages)
|
|
31
|
+
|
|
32
|
+
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives. `Mt5CliClient` remains available as a backward-compatible alias.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from datetime import UTC, datetime
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
from mt5cli import (
|
|
39
|
+
DataKind,
|
|
40
|
+
Dataset,
|
|
41
|
+
MT5Client,
|
|
42
|
+
build_config,
|
|
43
|
+
collect_history,
|
|
44
|
+
export_dataframe,
|
|
45
|
+
mt5_session,
|
|
46
|
+
normalize_dataframe,
|
|
47
|
+
update_history_with_config,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Persistent session for multiple calls
|
|
51
|
+
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
52
|
+
rates = client.copy_rates_range(
|
|
53
|
+
"EURUSD",
|
|
54
|
+
timeframe="H1",
|
|
55
|
+
date_from="2024-01-01",
|
|
56
|
+
date_to="2024-02-01",
|
|
57
|
+
)
|
|
58
|
+
positions = client.positions()
|
|
59
|
+
check = client.order_check({"action": 1, "symbol": "EURUSD", "volume": 0.1})
|
|
60
|
+
|
|
61
|
+
# Normalize MT5 frames to the public schema contract before storage
|
|
62
|
+
closed_rates = normalize_dataframe(
|
|
63
|
+
rates, DataKind.rates, symbol="EURUSD", timeframe="H1"
|
|
64
|
+
)
|
|
65
|
+
export_dataframe(closed_rates, Path("rates.csv"), "csv")
|
|
66
|
+
|
|
67
|
+
# Bulk SQLite history (same behavior as collect-history CLI command)
|
|
68
|
+
collect_history(
|
|
69
|
+
Path("history.db"),
|
|
70
|
+
symbols=["EURUSD"],
|
|
71
|
+
date_from=datetime(2024, 1, 1, tzinfo=UTC),
|
|
72
|
+
date_to=datetime(2024, 2, 1, tzinfo=UTC),
|
|
73
|
+
datasets={Dataset.rates, Dataset.history_deals},
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Incremental append for automated pipelines
|
|
77
|
+
update_history_with_config(
|
|
78
|
+
output="history.db",
|
|
79
|
+
symbols=["EURUSD"],
|
|
80
|
+
config=build_config(login=12345),
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
|
|
85
|
+
|
|
86
|
+
`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.
|
|
87
|
+
|
|
88
|
+
## CLI usage
|
|
31
89
|
|
|
32
90
|
```bash
|
|
33
91
|
# Export account information to CSV
|
|
@@ -161,7 +219,7 @@ eurusd_m1 = rates["EURUSD", "M1"] # closed bars only
|
|
|
161
219
|
- **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).
|
|
162
220
|
- **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. The read-only `mt5_session()` / `Mt5CliClient` SDK is unchanged.
|
|
163
221
|
- **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.
|
|
164
|
-
- **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 `
|
|
222
|
+
- **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.
|
|
165
223
|
- **SQLite export helpers**: use `export_dataframe_to_sqlite()` for append mode, optional index export, and post-write deduplication by key columns.
|
|
166
224
|
- **Recent ticks and margins**: `recent_ticks()` and `minimum_margins()` SDK helpers (and matching CLI commands) cover common downstream read-only queries.
|
|
167
225
|
|
|
@@ -226,7 +284,7 @@ finally:
|
|
|
226
284
|
client.shutdown()
|
|
227
285
|
```
|
|
228
286
|
|
|
229
|
-
Read-only collectors can keep using `mt5_session()` and `Mt5CliClient` without changes.
|
|
287
|
+
Read-only collectors can keep using `mt5_session()` and `MT5Client` (or the `Mt5CliClient` alias) without changes.
|
|
230
288
|
|
|
231
289
|
## Development
|
|
232
290
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
This section documents the mt5cli public Python API and CLI modules.
|
|
4
|
+
|
|
5
|
+
## Public API layers
|
|
6
|
+
|
|
7
|
+
| Module | Purpose |
|
|
8
|
+
| ----------------------------------------- | ------------------------------------------------------------------------- |
|
|
9
|
+
| [Client](client.md) | `MT5Client` session abstraction for data access and order primitives |
|
|
10
|
+
| [Schemas](schemas.md) | Canonical DataFrame contracts and normalization helpers |
|
|
11
|
+
| [Storage](storage.md) | CSV/JSON/Parquet/SQLite export and history collection helpers |
|
|
12
|
+
| [Converters](converters.md) | Symbol, timeframe, timezone, and date-range utilities |
|
|
13
|
+
| [Exceptions](exceptions.md) | Stable mt5cli exception types and MT5 error normalization |
|
|
14
|
+
| [SDK](sdk.md) | Module-level fetch helpers, multi-account collectors, incremental history |
|
|
15
|
+
| [Trading](trading.md) | Trading-capable sessions and operational helpers |
|
|
16
|
+
| [History Collection (SQLite)](history.md) | SQLite schema, incremental writes, dedup, and rate views |
|
|
17
|
+
| [CLI](cli.md) | Typer commands that delegate to the Python API |
|
|
18
|
+
| [Utils](utils.md) | Parsing helpers and Click parameter types |
|
|
19
|
+
|
|
20
|
+
## Architecture overview
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart TD
|
|
24
|
+
App["Downstream application"] --> Client["MT5Client"]
|
|
25
|
+
CLI["mt5cli CLI"] --> Client
|
|
26
|
+
Client --> SDK["sdk / pdmt5"]
|
|
27
|
+
Client --> Schemas["schemas"]
|
|
28
|
+
Storage["storage"] --> History["history SQLite"]
|
|
29
|
+
Storage --> Utils["utils export"]
|
|
30
|
+
SDK --> PDMT5["pdmt5.Mt5DataClient"]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Downstream packages should depend on the package root exports (`MT5Client`, `DataKind`, `normalize_dataframe`, `export_dataframe`, `collect_history`, etc.) rather than private modules.
|
|
34
|
+
|
|
35
|
+
`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.
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from mt5cli import MT5Client, build_config, mt5_session
|
|
41
|
+
|
|
42
|
+
with mt5_session(build_config(login=12345)) as client:
|
|
43
|
+
rates = client.copy_rates_range("EURUSD", "H1", "2024-01-01", "2024-02-01")
|
|
44
|
+
positions = client.positions()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mt5cli -o account.csv account-info
|
|
49
|
+
mt5cli -o rates.parquet rates-range --symbol EURUSD --timeframe H1 \
|
|
50
|
+
--date-from 2024-01-01 --date-to 2024-02-01
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
See individual module pages for detailed usage examples.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# mt5cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Generic MT5 data and execution infrastructure for Python applications.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
mt5cli
|
|
7
|
+
mt5cli provides a stable `MT5Client` Python API, standardized dataset schemas, storage helpers, and a CLI for exporting MetaTrader 5 data. It is built on top of [pdmt5](https://github.com/dceoy/pdmt5), a pandas-based data handler for MetaTrader 5.
|
|
8
8
|
|
|
9
9
|
## Architecture
|
|
10
10
|
|
|
11
11
|
- **pdmt5** — canonical MT5 client, DataFrame/trading primitives, and MT5 constant parsing (`TIMEFRAME_*`, `COPY_TICKS_*`, order types).
|
|
12
|
-
- **mt5cli** —
|
|
12
|
+
- **mt5cli** — public `MT5Client` API, schema contracts, storage helpers, CLI commands, and SQLite history collection built on pdmt5.
|
|
13
13
|
- **mt5api** — sibling HTTP adapter for remote MT5 access; not a dependency of mt5cli.
|
|
14
14
|
|
|
15
15
|
## Features
|
|
@@ -27,66 +27,68 @@ mt5cli is a CLI application that exports MetaTrader 5 trading data to multiple f
|
|
|
27
27
|
pip install mt5cli
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Python API for downstream packages
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Import `MT5Client` for generic MT5 data access, schema normalization, and optional order primitives. `Mt5CliClient` remains available as a backward-compatible alias.
|
|
33
33
|
|
|
34
34
|
```python
|
|
35
35
|
from datetime import UTC, datetime
|
|
36
36
|
from pathlib import Path
|
|
37
37
|
|
|
38
38
|
from mt5cli import (
|
|
39
|
-
|
|
39
|
+
DataKind,
|
|
40
|
+
Dataset,
|
|
41
|
+
MT5Client,
|
|
42
|
+
build_config,
|
|
40
43
|
collect_history,
|
|
41
|
-
copy_rates_range,
|
|
42
44
|
export_dataframe,
|
|
43
|
-
export_dataframe_to_sqlite,
|
|
44
45
|
load_rate_data,
|
|
45
46
|
minimum_margins,
|
|
47
|
+
mt5_session,
|
|
48
|
+
normalize_dataframe,
|
|
46
49
|
recent_ticks,
|
|
50
|
+
resolve_rate_view_name,
|
|
47
51
|
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
rates = copy_rates_range(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
|
|
53
|
+
# Persistent session for multiple calls
|
|
54
|
+
with mt5_session(build_config(login=12345, server="Broker-Demo")) as client:
|
|
55
|
+
rates = client.copy_rates_range(
|
|
56
|
+
"EURUSD",
|
|
57
|
+
timeframe="H1",
|
|
58
|
+
date_from="2024-01-01",
|
|
59
|
+
date_to="2024-02-01",
|
|
60
|
+
)
|
|
61
|
+
positions = client.positions()
|
|
62
|
+
check = client.order_check({"action": 1, "symbol": "EURUSD", "volume": 0.1})
|
|
63
|
+
|
|
64
|
+
# Normalize MT5 frames to the public schema contract before storage
|
|
65
|
+
closed_rates = normalize_dataframe(
|
|
66
|
+
rates, DataKind.rates, symbol="EURUSD", timeframe="H1"
|
|
56
67
|
)
|
|
57
|
-
export_dataframe(
|
|
68
|
+
export_dataframe(closed_rates, Path("rates.csv"), "csv")
|
|
58
69
|
|
|
59
|
-
#
|
|
70
|
+
# Offline rate loading from mt5cli-managed SQLite history
|
|
60
71
|
view = resolve_rate_view_name(Path("history.db"), "EURUSD", "M1", require_existing=True)
|
|
61
72
|
offline_rates = load_rate_data(Path("history.db"), view, count=1000)
|
|
62
73
|
|
|
63
|
-
#
|
|
74
|
+
# One-off helpers still work without instantiating a client
|
|
64
75
|
ticks = recent_ticks("EURUSD", seconds=300)
|
|
65
76
|
margins = minimum_margins("EURUSD")
|
|
66
77
|
|
|
67
|
-
# Reuse one MT5 connection for multiple calls
|
|
68
|
-
with Mt5CliClient(login=12345, password="secret", server="Broker-Demo") as client:
|
|
69
|
-
account = client.account_info()
|
|
70
|
-
positions = client.positions()
|
|
71
|
-
latest = client.latest_rates("EURUSD", "M1", count=100)
|
|
72
|
-
summary = client.mt5_summary()
|
|
73
|
-
summary_table = client.mt5_summary_as_df()
|
|
74
|
-
|
|
75
|
-
# Bulk SQLite collection (same behavior as the collect-history CLI command)
|
|
76
78
|
collect_history(
|
|
77
79
|
Path("history.db"),
|
|
78
80
|
symbols=["EURUSD", "GBPUSD"],
|
|
79
81
|
date_from=datetime(2024, 1, 1, tzinfo=UTC),
|
|
80
82
|
date_to=datetime(2024, 2, 1, tzinfo=UTC),
|
|
81
|
-
|
|
82
|
-
flags="ALL",
|
|
83
|
-
with_views=True,
|
|
83
|
+
datasets={Dataset.rates, Dataset.history_deals},
|
|
84
84
|
)
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Schema contracts live in `mt5cli.schemas` (`DataKind`, `validate_schema`, `normalize_dataframe`). Storage helpers are re-exported from `mt5cli.storage` and the package root.
|
|
88
|
+
|
|
89
|
+
`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`).
|
|
88
90
|
|
|
89
|
-
`
|
|
91
|
+
`MT5Client.mt5_summary()` returns structured nested Python values. Use `MT5Client.mt5_summary_as_df()` when you need a one-row DataFrame for export.
|
|
90
92
|
|
|
91
93
|
## Quick Start
|
|
92
94
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
site_name: mt5cli API Documentation
|
|
2
|
-
site_description:
|
|
2
|
+
site_description: Generic MT5 data and execution infrastructure for Python
|
|
3
3
|
site_author: dceoy
|
|
4
4
|
site_url: https://github.com/dceoy/mt5cli
|
|
5
5
|
|
|
@@ -56,6 +56,11 @@ nav:
|
|
|
56
56
|
- Home: index.md
|
|
57
57
|
- API Reference:
|
|
58
58
|
- Overview: api/index.md
|
|
59
|
+
- Client: api/client.md
|
|
60
|
+
- Schemas: api/schemas.md
|
|
61
|
+
- Storage: api/storage.md
|
|
62
|
+
- Converters: api/converters.md
|
|
63
|
+
- Exceptions: api/exceptions.md
|
|
59
64
|
- CLI: api/cli.md
|
|
60
65
|
- SDK: api/sdk.md
|
|
61
66
|
- Trading: api/trading.md
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
"""mt5cli:
|
|
1
|
+
"""mt5cli: Generic MT5 data and execution infrastructure for Python applications."""
|
|
2
2
|
|
|
3
3
|
from importlib.metadata import version
|
|
4
4
|
|
|
5
|
+
from .client import MT5Client, build_config, mt5_session
|
|
6
|
+
from .converters import (
|
|
7
|
+
ensure_utc,
|
|
8
|
+
granularity_name,
|
|
9
|
+
normalize_symbol,
|
|
10
|
+
normalize_symbols,
|
|
11
|
+
parse_date_range,
|
|
12
|
+
recent_window,
|
|
13
|
+
)
|
|
14
|
+
from .exceptions import (
|
|
15
|
+
Mt5CliError,
|
|
16
|
+
Mt5ConnectionError,
|
|
17
|
+
Mt5OperationError,
|
|
18
|
+
Mt5SchemaError,
|
|
19
|
+
call_with_normalized_errors,
|
|
20
|
+
is_recoverable_mt5_error,
|
|
21
|
+
normalize_mt5_exception,
|
|
22
|
+
)
|
|
5
23
|
from .history import (
|
|
6
24
|
RateTarget,
|
|
7
25
|
build_rate_targets,
|
|
@@ -18,12 +36,22 @@ from .history import (
|
|
|
18
36
|
resolve_rate_view_name,
|
|
19
37
|
resolve_rate_view_names,
|
|
20
38
|
)
|
|
39
|
+
from .schemas import (
|
|
40
|
+
DEDUP_KEYS,
|
|
41
|
+
KNOWN_MT5_TIME_COLUMNS,
|
|
42
|
+
REQUIRED_COLUMNS,
|
|
43
|
+
TIME_COLUMNS,
|
|
44
|
+
DataKind,
|
|
45
|
+
normalize_dataframe,
|
|
46
|
+
normalize_time_columns,
|
|
47
|
+
schema_columns,
|
|
48
|
+
validate_schema,
|
|
49
|
+
)
|
|
21
50
|
from .sdk import (
|
|
22
51
|
AccountSpec,
|
|
23
52
|
Mt5CliClient,
|
|
24
53
|
ThrottledHistoryUpdater,
|
|
25
54
|
account_info,
|
|
26
|
-
build_config,
|
|
27
55
|
collect_history,
|
|
28
56
|
collect_latest_closed_rates_by_granularity,
|
|
29
57
|
collect_latest_closed_rates_for_accounts,
|
|
@@ -41,7 +69,6 @@ from .sdk import (
|
|
|
41
69
|
latest_rates,
|
|
42
70
|
market_book,
|
|
43
71
|
minimum_margins,
|
|
44
|
-
mt5_session,
|
|
45
72
|
mt5_summary,
|
|
46
73
|
mt5_summary_as_df,
|
|
47
74
|
orders,
|
|
@@ -61,6 +88,13 @@ from .sdk import (
|
|
|
61
88
|
from .sdk import (
|
|
62
89
|
version as mt5_version,
|
|
63
90
|
)
|
|
91
|
+
from .storage import (
|
|
92
|
+
Dataset,
|
|
93
|
+
IfExists,
|
|
94
|
+
detect_format,
|
|
95
|
+
export_dataframe,
|
|
96
|
+
export_dataframe_to_sqlite,
|
|
97
|
+
)
|
|
64
98
|
from .trading import (
|
|
65
99
|
calculate_margin_and_volume,
|
|
66
100
|
detect_position_side,
|
|
@@ -70,11 +104,6 @@ from .trading import (
|
|
|
70
104
|
from .utils import (
|
|
71
105
|
TICK_FLAG_MAP,
|
|
72
106
|
TIMEFRAME_MAP,
|
|
73
|
-
Dataset,
|
|
74
|
-
IfExists,
|
|
75
|
-
detect_format,
|
|
76
|
-
export_dataframe,
|
|
77
|
-
export_dataframe_to_sqlite,
|
|
78
107
|
parse_datetime,
|
|
79
108
|
parse_tick_flags,
|
|
80
109
|
parse_timeframe,
|
|
@@ -83,12 +112,22 @@ from .utils import (
|
|
|
83
112
|
__version__ = version(__package__) if __package__ else None
|
|
84
113
|
|
|
85
114
|
__all__ = [
|
|
115
|
+
"DEDUP_KEYS",
|
|
116
|
+
"KNOWN_MT5_TIME_COLUMNS",
|
|
117
|
+
"REQUIRED_COLUMNS",
|
|
86
118
|
"TICK_FLAG_MAP",
|
|
87
119
|
"TIMEFRAME_MAP",
|
|
120
|
+
"TIME_COLUMNS",
|
|
88
121
|
"AccountSpec",
|
|
122
|
+
"DataKind",
|
|
89
123
|
"Dataset",
|
|
90
124
|
"IfExists",
|
|
125
|
+
"MT5Client",
|
|
91
126
|
"Mt5CliClient",
|
|
127
|
+
"Mt5CliError",
|
|
128
|
+
"Mt5ConnectionError",
|
|
129
|
+
"Mt5OperationError",
|
|
130
|
+
"Mt5SchemaError",
|
|
92
131
|
"RateTarget",
|
|
93
132
|
"ThrottledHistoryUpdater",
|
|
94
133
|
"account_info",
|
|
@@ -96,6 +135,7 @@ __all__ = [
|
|
|
96
135
|
"build_rate_targets",
|
|
97
136
|
"build_rate_view_name",
|
|
98
137
|
"calculate_margin_and_volume",
|
|
138
|
+
"call_with_normalized_errors",
|
|
99
139
|
"collect_history",
|
|
100
140
|
"collect_latest_closed_rates_by_granularity",
|
|
101
141
|
"collect_latest_closed_rates_for_accounts",
|
|
@@ -111,10 +151,13 @@ __all__ = [
|
|
|
111
151
|
"detect_position_side",
|
|
112
152
|
"determine_order_limits",
|
|
113
153
|
"drop_forming_rate_bar",
|
|
154
|
+
"ensure_utc",
|
|
114
155
|
"export_dataframe",
|
|
115
156
|
"export_dataframe_to_sqlite",
|
|
157
|
+
"granularity_name",
|
|
116
158
|
"history_deals",
|
|
117
159
|
"history_orders",
|
|
160
|
+
"is_recoverable_mt5_error",
|
|
118
161
|
"last_error",
|
|
119
162
|
"latest_rates",
|
|
120
163
|
"load_rate_data",
|
|
@@ -128,13 +171,20 @@ __all__ = [
|
|
|
128
171
|
"mt5_summary_as_df",
|
|
129
172
|
"mt5_trading_session",
|
|
130
173
|
"mt5_version",
|
|
174
|
+
"normalize_dataframe",
|
|
175
|
+
"normalize_mt5_exception",
|
|
176
|
+
"normalize_symbol",
|
|
177
|
+
"normalize_symbols",
|
|
178
|
+
"normalize_time_columns",
|
|
131
179
|
"orders",
|
|
180
|
+
"parse_date_range",
|
|
132
181
|
"parse_datetime",
|
|
133
182
|
"parse_tick_flags",
|
|
134
183
|
"parse_timeframe",
|
|
135
184
|
"positions",
|
|
136
185
|
"recent_history_deals",
|
|
137
186
|
"recent_ticks",
|
|
187
|
+
"recent_window",
|
|
138
188
|
"resolve_account_spec",
|
|
139
189
|
"resolve_account_specs",
|
|
140
190
|
"resolve_history_datasets",
|
|
@@ -143,6 +193,7 @@ __all__ = [
|
|
|
143
193
|
"resolve_rate_tables",
|
|
144
194
|
"resolve_rate_view_name",
|
|
145
195
|
"resolve_rate_view_names",
|
|
196
|
+
"schema_columns",
|
|
146
197
|
"substitute_env_placeholders",
|
|
147
198
|
"symbol_info",
|
|
148
199
|
"symbol_info_tick",
|
|
@@ -150,4 +201,5 @@ __all__ = [
|
|
|
150
201
|
"terminal_info",
|
|
151
202
|
"update_history",
|
|
152
203
|
"update_history_with_config",
|
|
204
|
+
"validate_schema",
|
|
153
205
|
]
|
|
@@ -12,6 +12,7 @@ import typer
|
|
|
12
12
|
from pdmt5 import Mt5Config
|
|
13
13
|
|
|
14
14
|
from . import sdk
|
|
15
|
+
from .client import MT5Client
|
|
15
16
|
from .utils import (
|
|
16
17
|
DATETIME_TYPE,
|
|
17
18
|
REQUEST_TYPE,
|
|
@@ -91,14 +92,14 @@ def _execute_export(
|
|
|
91
92
|
)
|
|
92
93
|
|
|
93
94
|
|
|
94
|
-
def _sdk_client(ctx: typer.Context) ->
|
|
95
|
+
def _sdk_client(ctx: typer.Context) -> MT5Client:
|
|
95
96
|
export_ctx = _get_export_context(ctx)
|
|
96
|
-
return
|
|
97
|
+
return MT5Client(config=export_ctx.config)
|
|
97
98
|
|
|
98
99
|
|
|
99
100
|
def _export_command(
|
|
100
101
|
ctx: typer.Context,
|
|
101
|
-
fetch_fn: Callable[[
|
|
102
|
+
fetch_fn: Callable[[MT5Client], pd.DataFrame],
|
|
102
103
|
) -> None:
|
|
103
104
|
"""Create an SDK client, fetch a DataFrame, and export it."""
|
|
104
105
|
client = _sdk_client(ctx)
|
|
@@ -573,15 +574,7 @@ def order_check(
|
|
|
573
574
|
],
|
|
574
575
|
) -> None:
|
|
575
576
|
"""Check funds sufficiency for a trading operation."""
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
def _fetch() -> pd.DataFrame:
|
|
579
|
-
return sdk._run_with_client( # noqa: SLF001 # pyright: ignore[reportPrivateUsage]
|
|
580
|
-
export_ctx.config,
|
|
581
|
-
lambda c: c.order_check_as_df(request=request),
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
_execute_export(ctx, _fetch)
|
|
577
|
+
_export_command(ctx, lambda client: client.order_check(request))
|
|
585
578
|
|
|
586
579
|
|
|
587
580
|
@app.command()
|
|
@@ -604,15 +597,7 @@ def order_send(
|
|
|
604
597
|
if not yes:
|
|
605
598
|
msg = "Pass --yes to send a live trade request."
|
|
606
599
|
raise typer.BadParameter(msg, param_hint="--yes")
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
def _fetch() -> pd.DataFrame:
|
|
610
|
-
return sdk._run_with_client( # noqa: SLF001 # pyright: ignore[reportPrivateUsage]
|
|
611
|
-
export_ctx.config,
|
|
612
|
-
lambda c: c.order_send_as_df(request=request),
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
_execute_export(ctx, _fetch)
|
|
600
|
+
_export_command(ctx, lambda client: client.order_send(request))
|
|
616
601
|
|
|
617
602
|
|
|
618
603
|
@app.command()
|