mt5cli 1.3.2__tar.gz → 1.3.3__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-1.3.2 → mt5cli-1.3.3}/PKG-INFO +1 -1
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/public-contract.md +1 -1
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/trading.md +64 -44
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/trading.py +352 -254
- {mt5cli-1.3.2 → mt5cli-1.3.3}/pyproject.toml +1 -1
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_trading.py +761 -738
- {mt5cli-1.3.2 → mt5cli-1.3.3}/uv.lock +1 -1
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.agents/skills/local-qa/SKILL.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.agents/skills/local-qa/scripts/qa.sh +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.agents/skills/mt5cli/SKILL.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.agents/skills/pr-feedback-triage/SKILL.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.claude/agents/codex.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.claude/settings.json +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/FUNDING.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/dependabot.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/renovate.json +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/workflows/ci.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/workflows/claude.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.github/workflows/release.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/.gitignore +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/AGENTS.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/CLAUDE.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/LICENSE +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/README.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/cli.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/client.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/converters.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/exceptions.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/grafana.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/history.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/index.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/marketdata.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/observability.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/schemas.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/telemetry.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/api/utils.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/docs/index.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/README.md +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/compose.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/dashboards/mt5cli-market.json +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/dashboards/mt5cli-overview.json +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/dashboards/mt5cli-trades.json +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/provisioning/dashboards/mt5cli.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/examples/grafana/provisioning/datasources/mt5cli-sqlite.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mkdocs.yml +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/__init__.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/__main__.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/cli.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/client.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/contract.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/converters.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/exceptions.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/grafana.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/history.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/marketdata.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/observability.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/retry.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/schemas.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/telemetry.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/mt5cli/utils.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/__init__.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/conftest.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_cli.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_client.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_contracts.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_examples.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_grafana.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_history.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_marketdata.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_observability.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_packaging.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_telemetry.py +0 -0
- {mt5cli-1.3.2 → mt5cli-1.3.3}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mt5cli
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.3
|
|
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>
|
|
@@ -102,7 +102,7 @@ strategy entries, exits, Kelly sizing, or signal logic.
|
|
|
102
102
|
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- |
|
|
103
103
|
| `get_account_snapshot`, `get_symbol_snapshot`, `get_tick_snapshot`, `get_positions_frame` | Normalized account/symbol/tick/position views |
|
|
104
104
|
| `extract_tick_price` | Positive finite bid/ask extraction from tick mappings |
|
|
105
|
-
| `TickClockNormalizer` | Connection-scoped,
|
|
105
|
+
| `TickClockNormalizer` | Connection-scoped, host-clock-validated UTC tick normalization |
|
|
106
106
|
| `TickClockCalibration` | Server-clock calibration diagnostics (offset, evidence, status) |
|
|
107
107
|
| `NormalizedTickSnapshot` | Typed latest-tick contract with raw vs validated UTC timestamps |
|
|
108
108
|
| `CalibrationStatus`, `ClockStatus` | Literal status types for clock calibration and normalization |
|
|
@@ -204,16 +204,27 @@ provide entry-deal classification, Kelly sizing, or any betting-specific helpers
|
|
|
204
204
|
|
|
205
205
|
## Timestamp sources and broker clock offsets
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
MetaQuotes documents `copy_ticks_range()` and `copy_rates_range()` results,
|
|
208
|
+
and the date bounds they accept, as UTC, and does not document a different
|
|
209
|
+
timezone contract for `symbol_info_tick()`. In production on at least one
|
|
210
|
+
OANDA-style broker/terminal, however, `symbol_info_tick()` returned epochs
|
|
211
|
+
carrying the broker's own wall-clock label (UTC+3), not true UTC: treating
|
|
212
|
+
`copy_ticks_range()` as an independent UTC reference for the live tick clock
|
|
213
|
+
was the direct cause of a production calibration failure (see
|
|
214
|
+
[dceoy/mteor#428](https://github.com/dceoy/mteor/issues/428)), because a
|
|
215
|
+
query window built from the host clock missed the live event entirely, off
|
|
216
|
+
by exactly the broker's offset. mt5cli does not call `copy_ticks_range()` or
|
|
217
|
+
`copy_rates_range()` to calibrate the live tick clock, and does not
|
|
218
|
+
independently verify their documented UTC contract on any broker or
|
|
219
|
+
terminal — treat copied-history timestamps as broker/terminal-dependent
|
|
220
|
+
absent evidence from your own broker/terminal combination.
|
|
211
221
|
|
|
212
222
|
`get_tick_snapshot()` preserves the numeric MT5 epoch value in `time`; it does
|
|
213
|
-
not expose pdmt5's timezone-naive `Timestamp` conversion or alter the instant
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
223
|
+
not expose pdmt5's timezone-naive `Timestamp` conversion or alter the instant,
|
|
224
|
+
and it never applies any offset correction. Any broker-specific offset
|
|
225
|
+
handling requires independent evidence — see `TickClockNormalizer` below —
|
|
226
|
+
and must be applied separately. Do not subtract a presumed UTC+2 or UTC+3
|
|
227
|
+
offset from a raw timestamp without that evidence.
|
|
217
228
|
|
|
218
229
|
No offset is applied automatically by history retrieval helpers.
|
|
219
230
|
|
|
@@ -251,47 +262,54 @@ A normalized snapshot keeps the raw/UTC distinction explicit:
|
|
|
251
262
|
|
|
252
263
|
### Calibration evidence
|
|
253
264
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
available.
|
|
265
|
+
`copy_ticks_range()` is not used for calibration: its documented UTC contract
|
|
266
|
+
is broker/terminal-dependent and not independently verified here (see
|
|
267
|
+
above), so it cannot serve as an out-of-band UTC reference. Instead, the only
|
|
268
|
+
independent reference available is **this process's own clock**: every
|
|
269
|
+
calibration poll
|
|
270
|
+
fetches one live `symbol_info_tick()` value and stamps it with
|
|
271
|
+
`datetime.now(UTC)` at the moment it is received. Comparing that host receipt
|
|
272
|
+
time against the tick's own server-labeled epoch yields one candidate offset,
|
|
273
|
+
which must align to a 30-minute increment within the realistic UTC-14..UTC+14
|
|
274
|
+
range. `time_msc` is preferred over second-resolution `time` when available.
|
|
275
|
+
|
|
276
|
+
A single poll is never trusted on its own. A closed, stale, or illiquid
|
|
277
|
+
symbol keeps returning the exact same last-traded tick, so its epoch never
|
|
278
|
+
changes between polls — that ordinary tick age is not calibration evidence.
|
|
279
|
+
Only a poll whose epoch _differs_ from the previous poll (comparison is
|
|
280
|
+
inequality, not "must increase": a genuine broker offset **decrease**, e.g. a
|
|
281
|
+
UTC+3 to UTC+2 DST fallback, relabels the next fresh event with a numerically
|
|
282
|
+
_smaller_ epoch than the last one observed under the old, larger offset)
|
|
283
|
+
proves the broker produced a new event, and only then is its offset computed.
|
|
264
284
|
|
|
265
285
|
An offset is accepted only after `min_agreeing_samples` (default 2)
|
|
266
|
-
**distinct**
|
|
267
|
-
|
|
286
|
+
**distinct** fresh tick events agree on the same rounded offset — repeated
|
|
287
|
+
polls of one unchanged tick never count as evidence, so an illiquid symbol
|
|
268
288
|
cannot self-confirm. Evidence can come from multiple samples of one actively
|
|
269
289
|
updating symbol (paced by `sample_interval_seconds`) or across several
|
|
270
|
-
symbols passed to the constructor
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
`_MAX_FUTURE_SKEW_SECONDS` (2 minutes) past the host clock's current time, in
|
|
275
|
-
addition to covering the full trailing `copied_window_seconds`. A live tick's
|
|
276
|
-
true UTC event is not always at or before the host clock — feed/broker clock
|
|
277
|
-
skew can put it a few seconds ahead — and without that tolerance the matching
|
|
278
|
-
copied row would never be queried, so calibration would always report
|
|
279
|
-
`no_matching_event`. The tolerance is bounded, not open-ended: an event
|
|
280
|
-
further ahead than `_MAX_FUTURE_SKEW_SECONDS` is still excluded from the
|
|
281
|
-
query and cannot be matched.
|
|
290
|
+
symbols passed to the constructor; a closed symbol among several configured
|
|
291
|
+
symbols simply contributes no evidence rather than blocking the others. Any
|
|
292
|
+
two fresh events that disagree on the rounded offset abort the calibration
|
|
293
|
+
(`offset_disagreement`) instead of being averaged or resolved by recency.
|
|
282
294
|
|
|
283
295
|
### Failure modes and fail-closed behavior
|
|
284
296
|
|
|
285
|
-
When calibration cannot be established safely —
|
|
286
|
-
(
|
|
287
|
-
(`
|
|
288
|
-
|
|
289
|
-
(`implausible_offset`)
|
|
297
|
+
When calibration cannot be established safely — no symbol ever produced a
|
|
298
|
+
fresh (changed-epoch) tick, e.g. every configured symbol is closed or
|
|
299
|
+
illiquid (`not_advancing`), a fresh event's raw offset does not round cleanly
|
|
300
|
+
to a plausible bucket (`unstable_offset`), an unrealistic rounded delta
|
|
301
|
+
(`implausible_offset`), too few distinct agreeing events
|
|
302
|
+
(`insufficient_agreement`), disagreeing events (`offset_disagreement`), or
|
|
303
|
+
missing live data (`no_live_tick`) — snapshots fail closed: `clock_status` is
|
|
290
304
|
`"uncalibrated"`, `time_utc` and `server_clock_offset_seconds` are `None`,
|
|
291
305
|
and the raw fields remain available. A raw timestamp is never silently
|
|
292
306
|
treated as UTC. `normalizer.calibration` exposes the full
|
|
293
307
|
`TickClockCalibration` diagnostics: status, offset, distinct sample count,
|
|
294
|
-
evidence symbols,
|
|
308
|
+
evidence symbols, last calibration time, and (for troubleshooting a failed
|
|
309
|
+
attempt) the most recently considered sample's symbol, raw server-labeled
|
|
310
|
+
time, host observation time, and raw (pre-rounding) offset —
|
|
311
|
+
`to_dict()` for serialization, and all of it is included in the one
|
|
312
|
+
concise warning logged per failed calibration attempt.
|
|
295
313
|
|
|
296
314
|
### Caching and revalidation
|
|
297
315
|
|
|
@@ -305,12 +323,14 @@ symbols and calls. A cached offset is recomputed in three cases:
|
|
|
305
323
|
future — evidence that the broker offset grew, e.g. a UTC+2 to UTC+3
|
|
306
324
|
transition.
|
|
307
325
|
- Periodically, at most once per `revalidation_interval_seconds` (default 5
|
|
308
|
-
minutes), configured
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
326
|
+
minutes), each configured symbol is polled once and compared against that
|
|
327
|
+
symbol's last known observation (from the initial calibration or a prior
|
|
328
|
+
revalidation) until one confirms the still-cached offset. Closed or
|
|
329
|
+
inconclusive symbols are skipped; a detected disagreement forces full
|
|
330
|
+
recalibration. This is what catches a broker offset _decrease_ (e.g. UTC+3
|
|
331
|
+
to UTC+2): the resulting normalized time looks stale rather than future,
|
|
332
|
+
which a future-skew check alone cannot distinguish from ordinary
|
|
333
|
+
quiet-market staleness.
|
|
314
334
|
|
|
315
335
|
If recalibration still cannot validate the timestamp, the snapshot fails
|
|
316
336
|
closed. Failed calibrations are recorded for diagnostics but never reused;
|