mt5cli 1.1.1__tar.gz → 1.1.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.
Files changed (71) hide show
  1. {mt5cli-1.1.1 → mt5cli-1.1.2}/.agents/skills/pr-feedback-triage/SKILL.md +25 -15
  2. mt5cli-1.1.2/.github/workflows/opencode.yml +72 -0
  3. {mt5cli-1.1.1 → mt5cli-1.1.2}/PKG-INFO +9 -3
  4. {mt5cli-1.1.1 → mt5cli-1.1.2}/README.md +5 -1
  5. mt5cli-1.1.2/docs/api/grafana.md +25 -0
  6. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/index.md +2 -0
  7. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/public-contract.md +2 -2
  8. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/sdk.md +5 -4
  9. mt5cli-1.1.2/docs/api/telemetry.md +50 -0
  10. {mt5cli-1.1.1 → mt5cli-1.1.2}/mkdocs.yml +2 -0
  11. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/exceptions.py +4 -14
  12. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/history.py +186 -58
  13. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/retry.py +2 -3
  14. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/sdk.py +12 -14
  15. {mt5cli-1.1.1 → mt5cli-1.1.2}/pyproject.toml +4 -2
  16. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_cli.py +471 -780
  17. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_contracts.py +29 -23
  18. mt5cli-1.1.2/tests/test_examples.py +92 -0
  19. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_grafana.py +376 -424
  20. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_history.py +1072 -349
  21. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_sdk.py +605 -555
  22. mt5cli-1.1.2/tests/test_telemetry.py +312 -0
  23. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_trading.py +580 -733
  24. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/test_utils.py +167 -144
  25. {mt5cli-1.1.1 → mt5cli-1.1.2}/uv.lock +115 -108
  26. mt5cli-1.1.1/tests/test_examples.py +0 -75
  27. mt5cli-1.1.1/tests/test_telemetry.py +0 -249
  28. {mt5cli-1.1.1 → mt5cli-1.1.2}/.agents/skills/local-qa/SKILL.md +0 -0
  29. {mt5cli-1.1.1 → mt5cli-1.1.2}/.agents/skills/local-qa/scripts/qa.sh +0 -0
  30. {mt5cli-1.1.1 → mt5cli-1.1.2}/.agents/skills/mt5cli/SKILL.md +0 -0
  31. {mt5cli-1.1.1 → mt5cli-1.1.2}/.claude/agents/codex.md +0 -0
  32. {mt5cli-1.1.1 → mt5cli-1.1.2}/.claude/settings.json +0 -0
  33. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/FUNDING.yml +0 -0
  34. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/dependabot.yml +0 -0
  35. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/renovate.json +0 -0
  36. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/workflows/ci.yml +0 -0
  37. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/workflows/claude.yml +0 -0
  38. {mt5cli-1.1.1 → mt5cli-1.1.2}/.github/workflows/release.yml +0 -0
  39. {mt5cli-1.1.1 → mt5cli-1.1.2}/.gitignore +0 -0
  40. {mt5cli-1.1.1 → mt5cli-1.1.2}/AGENTS.md +0 -0
  41. {mt5cli-1.1.1 → mt5cli-1.1.2}/CLAUDE.md +0 -0
  42. {mt5cli-1.1.1 → mt5cli-1.1.2}/LICENSE +0 -0
  43. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/cli.md +0 -0
  44. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/client.md +0 -0
  45. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/converters.md +0 -0
  46. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/exceptions.md +0 -0
  47. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/history.md +0 -0
  48. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/schemas.md +0 -0
  49. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/trading.md +0 -0
  50. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/api/utils.md +0 -0
  51. {mt5cli-1.1.1 → mt5cli-1.1.2}/docs/index.md +0 -0
  52. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/README.md +0 -0
  53. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/compose.yml +0 -0
  54. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/dashboards/mt5cli-market.json +0 -0
  55. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/dashboards/mt5cli-overview.json +0 -0
  56. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/dashboards/mt5cli-trades.json +0 -0
  57. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/provisioning/dashboards/mt5cli.yml +0 -0
  58. {mt5cli-1.1.1 → mt5cli-1.1.2}/examples/grafana/provisioning/datasources/mt5cli-sqlite.yml +0 -0
  59. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/__init__.py +0 -0
  60. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/__main__.py +0 -0
  61. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/cli.py +0 -0
  62. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/client.py +0 -0
  63. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/contract.py +0 -0
  64. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/converters.py +0 -0
  65. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/grafana.py +0 -0
  66. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/schemas.py +0 -0
  67. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/telemetry.py +0 -0
  68. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/trading.py +0 -0
  69. {mt5cli-1.1.1 → mt5cli-1.1.2}/mt5cli/utils.py +0 -0
  70. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/__init__.py +0 -0
  71. {mt5cli-1.1.1 → mt5cli-1.1.2}/tests/conftest.py +0 -0
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: pr-feedback-triage
3
3
  description: Triage pull request review comments into fixes, replies, clarification requests, or open follow-ups while respecting safe execution modes.
4
+ allowed-tools: Bash(git:*), Bash(gh:*), mcp__github__*, Read, Grep, Glob, Edit, MultiEdit, Write
4
5
  ---
5
6
 
6
7
  # PR Feedback Triage
@@ -43,9 +44,10 @@ When a mode disables an action, skip that destructive or externally visible acti
43
44
 
44
45
  Gather the complete feedback set before editing:
45
46
 
46
- - Fetch unresolved review threads, requested-change reviews, PR-level summary comments, and copied comments.
47
- - Use platform-native APIs/CLI when available. Paginate results; do not inspect only the first page of threads or comments.
48
- - For bot reviewers that post both summary comments and inline comments, collect both. Summary comments often contain severity, rationale, and fix instructions; inline comments contain the exact file and line context.
47
+ - Fetch unresolved review threads, requested-change reviews, inline comments, copied comments, and PR-level summary comments.
48
+ - Use whichever authenticated GitHub-capable interface is available and reliable. This skill explicitly permits both `gh` and GitHub MCP tools; paginate results and do not inspect only the first page of threads or comments.
49
+ - For bot reviewers that post both summary comments and inline comments, prefer inline comments for actionable triage. Incorporate summary findings only when they contain distinct severity, rationale, or fix instructions not already captured from inline comments.
50
+ - Summary comments may be excluded from triage when they do not add distinct actionable context.
49
51
  - Preserve every thread/comment identifier needed to reply or resolve later.
50
52
  - Compare each comment with the current diff and file contents because review lines can become outdated.
51
53
 
@@ -56,7 +58,7 @@ Build one triage record per distinct finding:
56
58
  - Prefer exact review-thread identity when available.
57
59
  - For duplicate bot findings appearing in both summary and inline comments, merge by exact issue title first, then by file path plus line range as a fallback.
58
60
  - Prefer inline comments for location and current code context.
59
- - Prefer summary comments for severity, category, rationale, and detailed agent prompts.
61
+ - Use summary comments only for distinct severity, category, rationale, or detailed agent prompts that are not already available from inline comments.
60
62
  - Preserve the reviewer’s exact issue title and original wording where practical. Do not rename findings in a way that would make replies hard to map back to comments.
61
63
  - Preserve the reviewer’s original ordering unless the user asks for priority reordering. Many review bots already order findings by severity.
62
64
 
@@ -70,13 +72,20 @@ Keep a thread open only when it still needs reviewer, maintainer, or product inp
70
72
 
71
73
  When resolving a thread, add a concise reply first only if it provides useful context, such as what changed, why no code change was needed, why a finding was intentionally deferred, or why the original comment is now outdated. Do not add noisy replies for self-evident fixes unless project norms require them.
72
74
 
75
+ ## Platform Comment Style
76
+
77
+ - Keep every posted reply or comment brief: one sentence by default, two short sentences only when necessary.
78
+ - Do not post PR-level summary or status comments by default. Omit them when they only restate completed fixes, resolved threads, or verification already visible in commits/checks.
79
+ - Avoid templates, long bullet lists, exhaustive status logs, and duplicated explanations in platform comments.
80
+ - For simple fixes, already-addressed findings, or outdated findings, prefer `resolve_only` over adding a reply.
81
+
73
82
  ## Platform Action Contract
74
83
 
75
- Do not treat triage as complete until every collected source ID reaches an explicit terminal state:
84
+ Do not treat triage as complete until every incorporated source ID reaches an explicit terminal state:
76
85
 
77
86
  - `resolved`: a platform resolve action succeeded, or a re-check shows the thread is already resolved.
78
87
  - `replied_left_open`: a reply or question was posted and the thread is intentionally left unresolved.
79
- - `not_resolvable`: the source is a PR-level summary comment or copied comment that has no platform-level resolve action; reply or post a PR summary when useful.
88
+ - `not_resolvable`: the source is a PR-level summary comment or copied comment that has no platform-level resolve action; post a brief reply only when useful.
80
89
  - `skipped_by_mode`: `dry_run`, `no_push`, or `no_reply` prevented the external action.
81
90
  - `failed_action`: a reply or resolve action was attempted and failed; include the attempted action and failure in the final summary.
82
91
 
@@ -85,13 +94,13 @@ In normal mode, build and execute a platform action queue after fixes are verifi
85
94
  - `reply_then_resolve`: use for handled threads where the reviewer needs context before resolution.
86
95
  - `resolve_only`: use for self-evident fixes and already-addressed or outdated threads where an extra reply would add noise.
87
96
  - `reply_leave_open`: use only for clarification requests, blocked work, or intentionally open follow-ups.
88
- - `reply_only`: use for PR-level comments or summaries that cannot be resolved as review threads.
97
+ - `reply_only`: use for PR-level comments or summaries that cannot be resolved, only when a short reply adds value.
89
98
 
90
99
  For duplicate findings, execute the terminal action for every source thread ID, not only the primary triage record. If one finding is represented by three unresolved inline threads, all three must be resolved or explicitly left open.
91
100
 
92
101
  ## GitHub Action Guidance
93
102
 
94
- Prefer platform-native APIs or `gh` commands that expose review-thread resolution state. For GitHub inline review threads, use the thread node ID and the GraphQL `resolveReviewThread` mutation rather than assuming that a reply resolves the conversation.
103
+ Use whichever authenticated GitHub-capable interface is available and reliable, preferably `gh` or GitHub MCP. Prefer interfaces that expose review-thread resolution state. For GitHub inline review threads, use the thread node ID and the GraphQL `resolveReviewThread` mutation, or an equivalent GitHub MCP resolve-thread tool, rather than assuming that a reply resolves the conversation.
95
104
 
96
105
  A reliable pattern is:
97
106
 
@@ -150,9 +159,9 @@ flowchart TD
150
159
  ## Compact Workflow
151
160
 
152
161
  1. **Collect all relevant feedback**
153
- - Identify the PR and gather unresolved review threads, requested-change reviews, PR-level summaries, inline comments, and copied comments.
162
+ - Identify the PR and gather unresolved review threads, requested-change reviews, inline comments, copied comments, and PR-level summaries.
154
163
  - Paginate all platform calls and keep comment/thread IDs for later replies and resolution.
155
- - For bot reviews, collect both summary and inline comments, then merge duplicates rather than fixing the same finding twice.
164
+ - For bot reviews, prioritize inline comments and incorporate summary findings only when they add distinct actionable context.
156
165
 
157
166
  2. **Classify each triage record**
158
167
  - **Fix**: Valid requested change; make the smallest focused edit when not in `dry_run`.
@@ -168,7 +177,7 @@ flowchart TD
168
177
  - In `dry_run`, stop at triage, proposed fixes, suggested replies, and verification plan.
169
178
  - In `no_push`, local edits are allowed, but do not push or resolve threads whose fix is only local. Reply or resolve non-code, already-addressed, or outdated threads only when the action does not depend on unpushed work and `no_reply` is not set.
170
179
  - In `no_reply`, do not post replies or resolve threads; report suggested replies/actions instead.
171
- - In normal mode, commit and push changed code when appropriate, then execute the platform action queue for every collected source ID.
180
+ - In normal mode, commit and push changed code when appropriate, then execute the platform action queue for every incorporated source ID.
172
181
 
173
182
  4. **Verify before claiming completion**
174
183
  - For fixes, run appropriate checks or explain why they could not run.
@@ -178,15 +187,16 @@ flowchart TD
178
187
  - If a resolve or reply operation fails, retry once when safe; then report `failed_action` with the affected source ID and reason.
179
188
 
180
189
  5. **Finish**
181
- - Normal mode: commit/push changes when appropriate, post useful replies or a summary, resolve all handled threads by default, and reconcile the final unresolved set.
190
+ - Normal mode: commit/push changes when appropriate, post only useful short replies/comments, omit PR-level summaries when they add no value, resolve all handled threads by default, and reconcile the final unresolved set.
182
191
  - Safe modes: report the local state and the exact replies/resolution actions a human could take.
183
192
 
184
193
  ## Reply Guidance
185
194
 
186
- - Keep inline replies short and tied to the original title or concern.
187
- - For fixed findings, mention the concrete change or commit if useful.
188
- - For already-addressed or outdated findings, cite the current code path or behavior that makes the finding no longer applicable.
195
+ - Keep inline replies short: one sentence by default, two short sentences only when needed.
196
+ - For fixed findings, mention the concrete change or commit only if it helps the reviewer.
197
+ - For already-addressed or outdated findings, cite the current code path or behavior only as briefly as needed.
189
198
  - For deferred or won't-fix findings, provide the reason and any follow-up issue or owner if known.
199
+ - Avoid posting PR-level summary comments unless they communicate a decision, blocker, or requested reviewer action.
190
200
  - If a reply or resolve operation fails, continue with the remaining threads and report the failure in the final summary.
191
201
 
192
202
  ## Final Summary Checklist
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: Pull request review and mention bot using OpenCode
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - ready_for_review
8
+ issue_comment:
9
+ types:
10
+ - created
11
+ pull_request_review_comment:
12
+ types:
13
+ - created
14
+ pull_request_review:
15
+ types:
16
+ - submitted
17
+ issues:
18
+ types:
19
+ - opened
20
+ - assigned
21
+ permissions:
22
+ contents: read
23
+ jobs:
24
+ opencode-review:
25
+ if: >
26
+ github.event_name == 'pull_request'
27
+ && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)
28
+ && (! github.event.pull_request.draft)
29
+ && (! startsWith(github.head_ref, 'dependabot/'))
30
+ && (! startsWith(github.head_ref, 'renovate/'))
31
+ permissions:
32
+ contents: read
33
+ pull-requests: write
34
+ issues: write
35
+ id-token: write
36
+ actions: read
37
+ uses: dceoy/gh-actions-for-devops/.github/workflows/opencode-review.yml@main # zizmor: ignore[unpinned-uses]
38
+ with:
39
+ model: opencode-go/kimi-k2.7-code
40
+ secrets:
41
+ OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
42
+ GH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
43
+ opencode-bot:
44
+ if: >
45
+ (
46
+ (github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment')
47
+ && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
48
+ && (contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode'))
49
+ ) || (
50
+ github.event_name == 'pull_request_review'
51
+ && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.review.author_association)
52
+ && (contains(github.event.review.body, '/oc') || contains(github.event.review.body, '/opencode'))
53
+ ) || (
54
+ github.event_name == 'issues'
55
+ && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association)
56
+ && (
57
+ (contains(github.event.issue.body, '/oc') || contains(github.event.issue.title, '/oc'))
58
+ || (contains(github.event.issue.body, '/opencode') || contains(github.event.issue.title, '/opencode'))
59
+ )
60
+ )
61
+ permissions:
62
+ contents: read
63
+ pull-requests: write
64
+ issues: write
65
+ id-token: write
66
+ actions: read
67
+ uses: dceoy/gh-actions-for-devops/.github/workflows/opencode-bot.yml@main # zizmor: ignore[unpinned-uses]
68
+ with:
69
+ model: opencode-go/glm-5.2
70
+ secrets:
71
+ OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
72
+ GH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mt5cli
3
- Version: 1.1.1
3
+ Version: 1.1.2
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,9 @@ 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>=1.0.0
20
+ Requires-Dist: pandas>=2.2.2
21
+ Requires-Dist: pdmt5>=1.0.4
22
+ Requires-Dist: pydantic>=2.13.4
21
23
  Requires-Dist: typer>=0.15.0
22
24
  Provides-Extra: otel
23
25
  Requires-Dist: opentelemetry-api; extra == 'otel'
@@ -331,7 +333,11 @@ WHERE run_id = (SELECT MAX(run_id) FROM snapshot_runs WHERE status = 'ok');
331
333
  SELECT symbol, total_profit FROM grafana_trade_stats ORDER BY total_profit DESC;
332
334
  ```
333
335
 
334
- > **Note**: OpenTelemetry integration is intentionally not part of this release and is tracked separately.
336
+ #### Grafana and telemetry API docs
337
+
338
+ The shipped Grafana helpers are documented in [`docs/api/grafana.md`](docs/api/grafana.md), including `publish_grafana_copy()` for creating a WAL-safe published SQLite copy for Grafana.
339
+
340
+ OpenTelemetry metrics are documented in [`docs/api/telemetry.md`](docs/api/telemetry.md), including `enable_otel_metrics()`, `configure_metrics()`, the `mt5cli[otel]` extra, and `OTEL_EXPORTER_OTLP_ENDPOINT`.
335
341
 
336
342
  ### Incremental history SDK
337
343
 
@@ -302,7 +302,11 @@ WHERE run_id = (SELECT MAX(run_id) FROM snapshot_runs WHERE status = 'ok');
302
302
  SELECT symbol, total_profit FROM grafana_trade_stats ORDER BY total_profit DESC;
303
303
  ```
304
304
 
305
- > **Note**: OpenTelemetry integration is intentionally not part of this release and is tracked separately.
305
+ #### Grafana and telemetry API docs
306
+
307
+ The shipped Grafana helpers are documented in [`docs/api/grafana.md`](docs/api/grafana.md), including `publish_grafana_copy()` for creating a WAL-safe published SQLite copy for Grafana.
308
+
309
+ OpenTelemetry metrics are documented in [`docs/api/telemetry.md`](docs/api/telemetry.md), including `enable_otel_metrics()`, `configure_metrics()`, the `mt5cli[otel]` extra, and `OTEL_EXPORTER_OTLP_ENDPOINT`.
306
310
 
307
311
  ### Incremental history SDK
308
312
 
@@ -0,0 +1,25 @@
1
+ # Grafana
2
+
3
+ ::: mt5cli.grafana
4
+
5
+ ## Grafana-ready SQLite workflow
6
+
7
+ Use `ensure_grafana_schema(conn)` or the `grafana-schema` CLI command to create
8
+ the snapshot tables, `grafana_*` views, and supporting indexes in one step.
9
+
10
+ `publish_grafana_copy(source, target)` creates a consistent SQLite copy via the
11
+ SQLite backup API, which is useful when the primary database is running in WAL
12
+ mode and Grafana should read from a separate published file.
13
+
14
+ ## Main APIs
15
+
16
+ - `ensure_grafana_schema()`: idempotently creates snapshot tables, Grafana
17
+ views, and indexes.
18
+ - `create_grafana_views()`: rebuilds the shipped `grafana_*` views.
19
+ - `create_grafana_indexes()`: creates read-oriented indexes for Grafana
20
+ queries.
21
+ - `publish_grafana_copy()`: writes an atomic, WAL-safe published copy for a
22
+ Grafana datasource.
23
+
24
+ For end-to-end snapshot collection examples, see the Grafana and observability
25
+ section in the project `README.md`.
@@ -18,6 +18,8 @@ responsibilities.
18
18
  | [SDK](sdk.md) | Module-level fetch helpers, multi-account collectors, incremental history |
19
19
  | [Trading](trading.md) | Trading-capable sessions and operational helpers |
20
20
  | [History Collection (SQLite)](history.md) | SQLite schema, incremental writes, dedup, and rate views |
21
+ | [Telemetry](telemetry.md) | OpenTelemetry metrics setup, meters, and emitted metric names |
22
+ | [Grafana](grafana.md) | Grafana-ready SQLite schema, views, snapshots, and published copies |
21
23
  | [CLI](cli.md) | Typer commands that delegate to the Python API |
22
24
  | [Utils](utils.md) | Parsing helpers and Click parameter types |
23
25
 
@@ -20,8 +20,8 @@ Downstream code should import raw pdmt5 types and constants (such as
20
20
  from `pdmt5` when needed. mt5cli does not serve as a pass-through compatibility
21
21
  namespace for pdmt5. mt5cli's trading helpers type their client parameter against
22
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.
23
+ longer required. `pdmt5.Mt5TradingError` was removed upstream in pdmt5 1.0.4;
24
+ mt5cli raises `Mt5OperationError` for all trading-related failures.
25
25
 
26
26
  Note: the former `mt5cli` re-export `TICK_FLAG_MAP` corresponds to `COPY_TICKS_MAP`
27
27
  in pdmt5 — the name changed, it was not simply moved.
@@ -12,8 +12,8 @@ application.
12
12
 
13
13
  `collect_latest_rates_for_accounts_with_retries()` wraps
14
14
  `collect_latest_rates_for_accounts()` with bounded exponential backoff. Only
15
- `pdmt5.Mt5TradingError` and `pdmt5.Mt5RuntimeError` are retried; the final
16
- failure is re-raised once `retry_count` is exhausted.
15
+ `pdmt5.Mt5RuntimeError` is retried; the final failure is re-raised once
16
+ `retry_count` is exhausted.
17
17
 
18
18
  ```python
19
19
  from mt5cli import AccountSpec, collect_latest_rates_for_accounts_with_retries
@@ -32,8 +32,9 @@ rates = collect_latest_rates_for_accounts_with_retries(
32
32
 
33
33
  MetaTrader 5 `start_pos=0` includes the still-forming current bar as the last
34
34
  row. `fetch_latest_closed_rates()` handles one connected `MT5Client`; use
35
- `fetch_latest_closed_rates_for_trading_client()` from an active
36
- `Mt5TradingClient` session. Multi-account helpers fetch `count + 1` bars, drop
35
+ `fetch_latest_closed_rates_for_trading_client()` from an active trading
36
+ session created by `create_trading_client()`. Multi-account helpers fetch
37
+ `count + 1` bars, drop
37
38
  that row with `drop_forming_rate_bar()`, and validate each series is non-empty. Returned frames are ordered
38
39
  oldest-to-newest and may contain fewer than `count` rows only when MT5 returns
39
40
  fewer closed bars.
@@ -0,0 +1,50 @@
1
+ # Telemetry
2
+
3
+ ::: mt5cli.telemetry
4
+
5
+ ## Enabling OpenTelemetry metrics
6
+
7
+ Install the optional exporter dependencies with:
8
+
9
+ ```bash
10
+ uv add 'mt5cli[otel]'
11
+ ```
12
+
13
+ Then enable the default OTLP HTTP pipeline:
14
+
15
+ ```python
16
+ from mt5cli.telemetry import enable_otel_metrics
17
+
18
+ enable_otel_metrics(service_name="mt5cli")
19
+ ```
20
+
21
+ When `readers=None`, `enable_otel_metrics()` builds a
22
+ `PeriodicExportingMetricReader` backed by the OTLP HTTP exporter and reads the
23
+ endpoint from `OTEL_EXPORTER_OTLP_ENDPOINT`.
24
+
25
+ If your application already owns an OpenTelemetry `Meter`, wire mt5cli into it
26
+ directly with `configure_metrics(meter)`.
27
+
28
+ ## Emitted metric names
29
+
30
+ `enable_otel_metrics()` / `configure_metrics()` register these instruments:
31
+
32
+ - `mt5_history_update_duration_seconds`
33
+ - `mt5_history_update_rows_total`
34
+ - `mt5_history_update_failures_total`
35
+ - `mt5_snapshot_update_duration_seconds`
36
+ - `mt5_snapshot_update_failures_total`
37
+ - `mt5_account_balance`
38
+ - `mt5_account_equity`
39
+ - `mt5_account_margin`
40
+ - `mt5_account_margin_free`
41
+ - `mt5_account_margin_level`
42
+ - `mt5_position_profit`
43
+ - `mt5_position_volume`
44
+ - `mt5_terminal_connected`
45
+ - `mt5_terminal_trade_allowed`
46
+ - `mt5_terminal_trade_expert`
47
+ - `mt5_last_successful_update_timestamp`
48
+
49
+ The history metrics use a `dataset` attribute. Account and position gauges add
50
+ labels such as `login`, `server`, and `symbol` where applicable.
@@ -65,6 +65,8 @@ nav:
65
65
  - SDK: api/sdk.md
66
66
  - Trading: api/trading.md
67
67
  - History Collection (SQLite): api/history.md
68
+ - Telemetry: api/telemetry.md
69
+ - Grafana: api/grafana.md
68
70
  - Utils: api/utils.md
69
71
 
70
72
  markdown_extensions:
@@ -9,11 +9,6 @@ from pdmt5 import Mt5RuntimeError
9
9
  if TYPE_CHECKING:
10
10
  from collections.abc import Callable
11
11
 
12
- try:
13
- from pdmt5 import Mt5TradingError
14
- except ImportError: # pragma: no cover
15
- Mt5TradingError = None # type: ignore[assignment]
16
-
17
12
  T = TypeVar("T")
18
13
 
19
14
  __all__ = [
@@ -26,10 +21,7 @@ __all__ = [
26
21
  "normalize_mt5_exception",
27
22
  ]
28
23
 
29
- _RECOVERABLE_MT5_ERRORS: tuple[type[BaseException], ...] = (
30
- *([Mt5TradingError] if Mt5TradingError is not None else []), # type: ignore[misc]
31
- Mt5RuntimeError,
32
- )
24
+ _RECOVERABLE_MT5_ERRORS: tuple[type[BaseException], ...] = (Mt5RuntimeError,)
33
25
 
34
26
 
35
27
  class Mt5CliError(Exception):
@@ -55,7 +47,7 @@ def is_recoverable_mt5_error(exc: BaseException) -> bool:
55
47
  exc: Exception raised by MT5 or pdmt5.
56
48
 
57
49
  Returns:
58
- True for ``Mt5RuntimeError`` and ``Mt5TradingError`` (if available).
50
+ True for ``Mt5RuntimeError``.
59
51
  """
60
52
  return isinstance(exc, _RECOVERABLE_MT5_ERRORS)
61
53
 
@@ -67,11 +59,9 @@ def normalize_mt5_exception(exc: BaseException) -> Mt5CliError:
67
59
  exc: Original exception from MT5 or pdmt5.
68
60
 
69
61
  Returns:
70
- ``Mt5ConnectionError`` for runtime failures, ``Mt5OperationError`` for
71
- trading failures, or the original exception when it is not recognized.
62
+ ``Mt5ConnectionError`` for runtime failures, or the original exception
63
+ when it is not recognized.
72
64
  """
73
- if Mt5TradingError is not None and isinstance(exc, Mt5TradingError):
74
- return Mt5OperationError(str(exc))
75
65
  if isinstance(exc, Mt5RuntimeError):
76
66
  return Mt5ConnectionError(str(exc))
77
67
  if isinstance(exc, Mt5CliError):