mt5cli 1.4.2__tar.gz → 1.6.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.
Files changed (86) hide show
  1. {mt5cli-1.4.2 → mt5cli-1.6.0}/.agents/skills/local-qa/scripts/qa.sh +2 -2
  2. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/workflows/claude.yml +2 -3
  3. {mt5cli-1.4.2 → mt5cli-1.6.0}/PKG-INFO +2 -2
  4. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/public-contract.md +49 -18
  5. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/history.py +754 -189
  6. mt5cli-1.6.0/mt5cli/lifecycle.py +87 -0
  7. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/observability.py +138 -36
  8. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/rates.py +60 -0
  9. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/sdk.py +11 -1
  10. {mt5cli-1.4.2 → mt5cli-1.6.0}/pyproject.toml +1 -1
  11. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_history.py +5 -3
  12. mt5cli-1.6.0/tests/unit/test_history_capture_persist.py +211 -0
  13. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_history_contract.py +166 -29
  14. mt5cli-1.6.0/tests/unit/test_lifecycle.py +145 -0
  15. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_observability.py +24 -2
  16. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_rates.py +29 -1
  17. {mt5cli-1.4.2 → mt5cli-1.6.0}/uv.lock +2 -2
  18. mt5cli-1.4.2/AGENTS.md +0 -29
  19. mt5cli-1.4.2/CLAUDE.md +0 -1
  20. {mt5cli-1.4.2 → mt5cli-1.6.0}/.agents/skills/local-qa/SKILL.md +0 -0
  21. {mt5cli-1.4.2 → mt5cli-1.6.0}/.agents/skills/mt5cli/SKILL.md +0 -0
  22. {mt5cli-1.4.2 → mt5cli-1.6.0}/.claude/agents/codex.md +0 -0
  23. {mt5cli-1.4.2 → mt5cli-1.6.0}/.claude/settings.json +0 -0
  24. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/CODEOWNERS +0 -0
  25. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/FUNDING.yml +0 -0
  26. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/dependabot.yml +0 -0
  27. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/renovate.json +0 -0
  28. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/workflows/ci.yml +0 -0
  29. {mt5cli-1.4.2 → mt5cli-1.6.0}/.github/workflows/release.yml +0 -0
  30. {mt5cli-1.4.2 → mt5cli-1.6.0}/.gitignore +0 -0
  31. {mt5cli-1.4.2 → mt5cli-1.6.0}/LICENSE +0 -0
  32. {mt5cli-1.4.2 → mt5cli-1.6.0}/README.md +0 -0
  33. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/cli.md +0 -0
  34. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/client.md +0 -0
  35. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/converters.md +0 -0
  36. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/exceptions.md +0 -0
  37. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/grafana.md +0 -0
  38. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/history.md +0 -0
  39. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/index.md +0 -0
  40. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/marketdata.md +0 -0
  41. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/observability.md +0 -0
  42. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/schemas.md +0 -0
  43. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/telemetry.md +0 -0
  44. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/trading.md +0 -0
  45. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/api/utils.md +0 -0
  46. {mt5cli-1.4.2 → mt5cli-1.6.0}/docs/index.md +0 -0
  47. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/README.md +0 -0
  48. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/compose.yml +0 -0
  49. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/dashboards/mt5cli-market.json +0 -0
  50. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/dashboards/mt5cli-overview.json +0 -0
  51. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/dashboards/mt5cli-trades.json +0 -0
  52. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/provisioning/dashboards/mt5cli.yml +0 -0
  53. {mt5cli-1.4.2 → mt5cli-1.6.0}/examples/grafana/provisioning/datasources/mt5cli-sqlite.yml +0 -0
  54. {mt5cli-1.4.2 → mt5cli-1.6.0}/mkdocs.yml +0 -0
  55. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/__init__.py +0 -0
  56. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/__main__.py +0 -0
  57. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/cli.py +0 -0
  58. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/client.py +0 -0
  59. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/contract.py +0 -0
  60. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/converters.py +0 -0
  61. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/exceptions.py +0 -0
  62. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/grafana.py +0 -0
  63. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/marketdata.py +0 -0
  64. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/retry.py +0 -0
  65. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/schemas.py +0 -0
  66. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/telemetry.py +0 -0
  67. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/trading.py +0 -0
  68. {mt5cli-1.4.2 → mt5cli-1.6.0}/mt5cli/utils.py +0 -0
  69. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/cli/test_cli.bats +0 -0
  70. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/__init__.py +0 -0
  71. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/conftest.py +0 -0
  72. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_cli.py +0 -0
  73. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_client.py +0 -0
  74. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_contracts.py +0 -0
  75. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_docs_contract.py +0 -0
  76. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_examples.py +0 -0
  77. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_grafana.py +0 -0
  78. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_history_edge_contract.py +0 -0
  79. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_marketdata.py +0 -0
  80. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_packaging.py +0 -0
  81. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_rate_timestamp_contract.py +0 -0
  82. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_rates_contract.py +0 -0
  83. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_stable_sdk_cleanup.py +0 -0
  84. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_telemetry.py +0 -0
  85. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_trading.py +0 -0
  86. {mt5cli-1.4.2 → mt5cli-1.6.0}/tests/unit/test_utils.py +0 -0
@@ -32,9 +32,9 @@ case "${OSTYPE}" in
32
32
  | xargs -0 -t shellcheck
33
33
 
34
34
  # GitHub Actions
35
- zizmor --fix=safe .github/workflows
35
+ uvx zizmor --fix=safe .github/workflows
36
36
  git ls-files -z -- '.github/workflows/*.yml' | xargs -0 -t actionlint
37
- checkov --framework=all --output=github_failed_only --directory=.
37
+ uvx checkov --framework=all --output=github_failed_only --directory=.
38
38
  ;;
39
39
  *)
40
40
  echo 'GitHub Actions and shell script linting is only supported on Linux and macOS.'
@@ -27,8 +27,7 @@ jobs:
27
27
  if: >
28
28
  github.event_name == 'pull_request'
29
29
  && (! github.event.pull_request.draft)
30
- && (! startsWith(github.head_ref, 'dependabot/'))
31
- && (! startsWith(github.head_ref, 'renovate/'))
30
+ && github.event.pull_request.user.type != 'Bot'
32
31
  permissions:
33
32
  contents: read
34
33
  pull-requests: write
@@ -46,7 +45,7 @@ jobs:
46
45
  || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude'))
47
46
  || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
48
47
  permissions:
49
- contents: read
48
+ contents: write
50
49
  pull-requests: write
51
50
  issues: write
52
51
  id-token: write
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: mt5cli
3
- Version: 1.4.2
3
+ Version: 1.6.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>
@@ -39,6 +39,7 @@ operational capability still has exactly one owning module:
39
39
  | Module | Owns |
40
40
  | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
41
41
  | `mt5cli.client` | Connection lifecycle (`build_config`, `mt5_session`, `MT5Client`); the sole session factory |
42
+ | `mt5cli.lifecycle` | Account selection within an already-active persistent MT5 session (`switch_account`) |
42
43
  | `mt5cli.marketdata` | Stateless one-off market-data reads and multi-account rate collection (`AccountSpec`, `collect_latest_rates_for_accounts`, etc.) |
43
44
  | `mt5cli.history` | Legacy history collection, incremental updates, and SQLite storage (`collect_history`, `update_history`, `write_*_dataset`) |
44
45
  | `mt5cli.rates` | Canonical rate persistence/loading and stable update wrappers (`load_rate_series_from_sqlite`, `update_history`, `ThrottledHistoryUpdater`) |
@@ -66,6 +67,7 @@ These names are exported from `mt5cli` and enumerated in
66
67
  | `build_config` | Build the underlying MT5 connection config 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` |
67
68
  | `substitute_mapping_values` | Generic selected-key environment substitution for downstream configuration adapters |
68
69
  | `mt5_session` | Canonical context manager: initialize/login once, yield `MT5Client`, shut down once; a supplied `client=` remains caller-owned. |
70
+ | `switch_account` | Change the account selected by an already-active persistent `MT5Client` with MT5 `login()` only; verifies the requested login/server and does not reinitialize or shut down the terminal |
69
71
  | `Mt5Config` | Canonical pdmt5 connection configuration type returned by `build_config` and accepted by managed-session wrappers |
70
72
  | `AccountSpec` | Generic account group: symbols plus optional credentials |
71
73
  | `resolve_account_spec`, `resolve_account_specs` | Merge overrides and expand `${ENV_VAR}` placeholders; opt-in `allow_whole_dollar_env` for bare `$NAME` |
@@ -87,17 +89,34 @@ timestamp normalization in downstream apps.
87
89
 
88
90
  ### SQLite history collection and rate loading
89
91
 
90
- | Symbol | Role |
91
- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
92
- | `collect_history` | One-shot date-range export into SQLite |
93
- | `report_rate_gaps` | SQLite-only one-row-per-gap report for the canonical rates table or an explicit custom table |
94
- | `update_history`, `update_history_with_config` | Incremental append from `MAX(time)` cursors; explicit naive trade-server `date_to` required |
95
- | `ThrottledHistoryUpdater` | Minimum interval between successful incremental updates; explicit `date_to`; optional `update_backend` injection |
96
- | `RateTarget`, `build_rate_targets` | Neutral `(symbol, timeframe)` series descriptors |
97
- | `load_rate_series_from_sqlite`, `load_rate_series_by_granularity` | Load normalized `rates` series or explicit custom tables; reject invalid targets clearly |
92
+ | Symbol | Role |
93
+ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
94
+ | `collect_history` | One-shot date-range export into SQLite |
95
+ | `report_rate_gaps` | SQLite-only one-row-per-gap report for the canonical rates table or an explicit custom table |
96
+ | `update_history`, `update_history_with_config` | Incremental append from `MAX(time)` cursors; explicit naive trade-server `date_to` required |
97
+ | `ThrottledHistoryUpdater` | Minimum interval between successful incremental updates; explicit `date_to`; optional `update_backend` injection |
98
+ | `capture_history_datasets` | MT5-bound half of `update_history`: resolves cursors and fetches MT5 data, returns a `HistoryCapture`, writes nothing |
99
+ | `persist_history_datasets` | MT5-free half of `update_history`: writes a `HistoryCapture` to SQLite (append/dedup/index/views); owns its own connection |
100
+ | `HistoryCapture` | Frozen, MT5-independent bundle returned by `capture_history_datasets` and consumed by `persist_history_datasets` |
101
+ | `RateTarget`, `build_rate_targets` | Neutral `(symbol, timeframe)` series descriptors |
102
+ | `load_rate_series_from_sqlite`, `load_rate_series_by_granularity` | Load normalized `rates` series or explicit custom tables; reject invalid targets clearly |
98
103
 
99
104
  See [History Collection (SQLite)](history.md) for the canonical schema, loading contract, and ER diagrams.
100
105
 
106
+ `update_history(client=...)` is exactly `capture_history_datasets(client=...)`
107
+ followed by `persist_history_datasets(...)` on the returned capture (skipped
108
+ when it is `None`, i.e. no datasets selected). Downstream applications that
109
+ must keep SQLite writes off an MT5-bound thread — for example a live trading
110
+ loop that cannot block on database I/O — call `capture_history_datasets` on
111
+ the thread holding the connected client, hand the returned `HistoryCapture` to
112
+ a separate persistence worker, and call `persist_history_datasets` there;
113
+ `persist_history_datasets` never accesses MT5 or any connection-scoped MT5
114
+ state. Capturing again for the same `output` before a prior capture has been
115
+ persisted re-reads the same not-yet-advanced incremental cursor and may
116
+ re-fetch an overlapping range (safe under `deduplicate=True`, but wasteful);
117
+ callers that queue persistence work should avoid capturing a new batch for a
118
+ target while one is still pending.
119
+
101
120
  Shared package-root helpers used by downstream adapters include `Dataset`,
102
121
  `parse_timeframe`, and `resolve_history_timeframes`. These are stable exports;
103
122
  downstream applications should not import them from `mt5cli.utils` or
@@ -184,16 +203,28 @@ idempotent (`CREATE TABLE IF NOT EXISTS`, `DROP VIEW IF EXISTS` + `CREATE
184
203
  VIEW`, `CREATE INDEX IF NOT EXISTS`). Missing source tables are skipped with a
185
204
  warning rather than raising an error.
186
205
 
187
- | Symbol | Role |
188
- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
189
- | `update_observability` | Append one timestamped snapshot row per data type from a connected client implementation |
190
- | `update_observability_with_config` | Standalone wrapper: opens/closes MT5 connection automatically around `update_observability` |
191
-
192
- Both functions write to the SQLite path given by `output=`. The optional
193
- `symbols` parameter filters `positions_get` / `orders_get` by symbol.
194
- `with_grafana_schema=False` (default) skips Grafana view/index setup; run
195
- `grafana-schema` once to set up the schema, then call `snapshot` repeatedly
196
- without this flag.
206
+ | Symbol | Role |
207
+ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
208
+ | `update_observability` | Append one timestamped snapshot row per data type from a connected client implementation |
209
+ | `update_observability_with_config` | Standalone wrapper: opens/closes MT5 connection automatically around `update_observability` |
210
+ | `capture_observability_snapshot` | MT5-bound half of `update_observability`: reads account/position/order/terminal state, returns an `ObservabilitySnapshot`, writes nothing |
211
+ | `persist_observability_snapshot` | MT5-free half of `update_observability`: writes an `ObservabilitySnapshot` to SQLite; owns its own connection |
212
+ | `ObservabilitySnapshot` | Frozen, MT5-independent bundle returned by `capture_observability_snapshot` and consumed by `persist_observability_snapshot` |
213
+
214
+ `update_observability` and `persist_observability_snapshot` write to the
215
+ SQLite path given by `output=`. The optional `symbols` parameter filters
216
+ `positions_get` / `orders_get` by symbol. `with_grafana_schema=False`
217
+ (default) skips Grafana view/index setup; run `grafana-schema` once to set up
218
+ the schema, then call `snapshot` repeatedly without this flag.
219
+
220
+ `update_observability(client=...)` is exactly
221
+ `capture_observability_snapshot(client=...)` followed by
222
+ `persist_observability_snapshot(...)`. As with history, a downstream
223
+ application that must keep SQLite writes off an MT5-bound thread calls
224
+ `capture_observability_snapshot` on the thread holding the connected client
225
+ and hands the returned `ObservabilitySnapshot` to a separate persistence
226
+ worker; `persist_observability_snapshot` never accesses MT5 or any
227
+ connection-scoped MT5 state.
197
228
 
198
229
  Pass the `MT5Client` yielded by `mt5_session()` directly to both
199
230
  `update_history(client=...)` and `update_observability(client=...)`. These