* feat: clarify CLI/docs scope as generic MT5 data and execution infrastructure
- Update app help text and module docstring to describe mt5cli as MT5 data
and execution utilities rather than export-only tooling
- Group CLI commands under rich_help_panel sections: Data / Export, Execution,
and Collection; command names are unchanged for compatibility
- Expand order-send docstring to explicitly flag it as the expert raw-request
live-trading path; preserve --yes gate
- Split docs/index.md Trading section into "Trading State" (read-only) and
"Execution (live / mutating)" with close-positions now documented
- Add TestHelpText tests verifying top-level panel grouping, order-send
expert/live language, and close-positions safety gate coverage
Closes#78
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
* chore: trim trailing whitespace in docs/index.md table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
* chore: bump version to 1.0.1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
* chore: update uv.lock for version 1.0.1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
* fix: address review feedback on CLI/docs scope PR
- Remove dead help invocation in test_order_send_help_mentions_expert_and_raw
(the result was immediately overwritten by result2)
- Strengthen assertion from `or` to `and`; both "raw" and "expert" are present
in the docstring so disjunction masked a potential regression
- Split into two `assert` statements to satisfy PT018 (ruff)
- Fix docs/index.md inaccuracy: order-check has no --yes gate; clarify that
only order-send and close-positions require confirmation for live execution
- Move order-check from "Execution" rich_help_panel to "Data / Export" so the
Execution panel name is truthful (order-check is read-only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
* docs: move order-check out of Execution section into Trading State
order-check is read-only and now lives in the CLI's Data / Export panel,
so documenting it under "Execution (live / mutating)" was inconsistent.
Moved it to the Trading State table. The Execution section now only lists
order-send and close-positions, both of which require --yes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018yH6esaqc5D1cmo1dK2Ur9
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: decouple mt5cli from pdmt5 high-level trading helpers
- Replace Mt5TradingClient type annotations with internal _Mt5ClientProtocol
- Lazy-import Mt5TradingClient in create_trading_client to avoid hard dependency
- Replace Mt5TradingError with Mt5OperationError in mt5cli validation paths
- Update exception handling to support future pdmt5 versions without Mt5TradingError
- Add test to enforce that mt5cli doesn't import high-level symbols at module level
- Update documentation to clarify dependency boundaries
mt5cli now relies only on low-level MT5 primitives:
- Mt5Config for configuration
- Mt5RuntimeError for runtime errors
- Raw MT5 methods (order_send, order_check, account_info, etc.)
This aligns with pdmt5's direction to remove high-level trading helpers and focus
on low-level MT5 access plus DataFrame/dict conversion.
Fixes#75 (dceoy/mt5cli#75)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PcGVFTVgyqzse3LLw38ber
* fix: address PR #76 review feedback on pdmt5 decoupling
- Replace Mt5TradingClient with Mt5DataClient in create_trading_client()
so the function no longer depends on the high-level trading client
- Fix _RECOVERABLE_MT5_ERRORS in exceptions.py to use tuple unpacking
form, removing the incorrect ternary assignment
- Add pragma: no cover to except ImportError branches in exceptions.py
and sdk.py (dead code when pdmt5 is installed)
- Switch coverage exclude_lines to exclude_also so the default
pragma: no cover pattern is preserved; also exclude bare ... stubs
(Protocol method bodies) from coverage
- Correct inaccurate note in docs/api/public-contract.md: Mt5TradingClient
is no longer required internally; Mt5TradingError is conditionally
available but mt5cli raises Mt5OperationError for trading failures
- Update all mock patches from pdmt5.Mt5TradingClient to
mt5cli.trading.Mt5DataClient to match the new module-level import
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add close-positions CLI command and replace_symbol projection mode (#65#66)
Part 1 — close-positions CLI (#65):
- Add `close-positions` subcommand delegating to `close_open_positions()`.
- Accepts repeated `--symbol` and `--ticket` filters (AND semantics).
- Supports `--dry-run` (no `--yes` required); live execution requires `--yes`.
- Fails closed with `BadParameter` when neither `--symbol` nor `--ticket` is given.
- Exports normalized `OrderExecutionResult` list as a DataFrame (request/response
serialized as JSON strings for clean CSV/JSON/Parquet/SQLite output).
- `order-send` remains the raw expert path; `close-positions` is the safer
high-level helper that builds correct close requests automatically.
Part 2 — ProjectionMode and replace_symbol (#66):
- Add `ProjectionMode = Literal["add", "replace_symbol"]` type alias.
- Add optional `projection_mode` parameter to `calculate_symbol_group_margin_ratio`.
Default `"add"` preserves existing additive behavior.
`"replace_symbol"` subtracts current margin for `new_symbol`, then adds
candidate margin — the subtraction and addition are atomic (suppressed together).
- Export `ProjectionMode` from `mt5cli` and add to `STABLE_SDK_EXPORTS`.
- No mteor-specific strategy, risk-threshold, or policy logic added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: remove unused ProjectionMode import in test_contracts.py
The parametrized test_stable_exports_are_importable_from_package_root
already covers ProjectionMode via hasattr(mt5cli, name). Ruff correctly
flagged the explicit top-level import as unused (F401).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Bump version to v0.9.6
* fix: address PR #67 review feedback
- Floor replace_symbol margin subtraction at zero to prevent negative ratio
- Serialize response unconditionally via json.dumps (null for dry-run rows)
- Return a schema-preserving empty DataFrame when results list is empty
- Add test: --dry-run --yes precedence (dry-run wins, no order_send)
- Add test: zero-match filter produces empty JSON array with exit 0
- Move projection_mode prose to stable trading section in docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add runtime validation for projection_mode in calculate_symbol_group_margin_ratio
Unsupported values previously silently fell through as "add". The new
_validate_projection_mode helper raises ValueError with a message that
names the bad value and the two accepted modes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: agent <agent@localhost>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: support string login in build_config and add substitute_mapping_values (#61, #62)
Extend build_config() to accept login: int | str | None. String logins
are coerced via the existing coerce_login() helper (empty/whitespace →
None, numeric strings → int, non-numeric → ValueError). When
allow_whole_dollar_env=True, ${ENV} and $ENV placeholders are expanded
before coercion, consistent with path/password/server behavior.
Add substitute_mapping_values(), a generic recursive helper that
substitutes environment placeholders in nested dicts/lists only for
caller-selected mapping keys. Non-selected fields (including literal
dollar signs) are preserved exactly. Supports blank_string_keys_as_none
to normalise empty strings to None after substitution. No application-
specific key names (e.g. mt5_login) are hard-coded in mt5cli.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Bump version to v0.9.5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs+test: clarify substitute_mapping_values docstring and pin tuple behaviour
- Adds sentence noting list-element strings are never substituted (only
immediate dict values are), addressing reviewer finding #1.
- Rewrites Returns section to accurately describe scalar pass-through
behaviour, addressing reviewer finding #2.
- Adds recursion-depth caveat to the generic-utility docstring,
addressing reviewer finding #4.
- Adds test_tuple_container_not_traversed to pin the existing silent
tuple-exclusion contract, addressing reviewer finding #3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update public contract and README for build_config login coercion and substitute_mapping_values
- Expands build_config row to document login: int | str | None,
numeric-string coercion, blank-string handling, and env placeholder
expansion when allow_whole_dollar_env=True.
- Adds substitute_mapping_values to the stable SDK table with a note
that key names are never hard-coded in mt5cli.
- Extends allow_whole_dollar_env paragraph to list substitute_mapping_values.
- README: adds build_config env-placeholder example and imports to the
trading lifecycle snippet.
- README: extends credential-resolution bullet with a substitute_mapping_values
usage example using generic key names.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: agent <agent@localhost>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: re-verify normalized volume margin before returning from calculate_volume_by_margin
For CFDs, index products, and tiered-margin instruments, the initial
min-lot margin estimate can be optimistic; the normalized stepped volume
may require more margin than available_margin. After computing the
normalized volume, step down by volume_step until order_calc_margin
confirms affordability, or return 0.0 if no step is affordable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: fix ruff line-length violations in calculate_volume_by_margin tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: use integer step index and add actual>0 guard in calculate_volume_by_margin
Replace float-subtraction loop with integer step index to eliminate
accumulation rounding error and add `actual > 0` guard so a broker
returning zero/negative margin is never accepted as affordable.
Inline `capped` to keep local-variable count within Ruff PLR0914 limit.
Update docstring to reflect re-verification behaviour and 0.0 fallback.
Tighten test assertion from `volume > 0` to the symbol's valid range.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Bump version to v0.9.1
* perf: replace linear step-down scan with binary search in calculate_volume_by_margin
Resolves the P2 review finding: the previous O(n) loop called
order_calc_margin once per volume step, making sizing appear hung for
symbols with a large step range or small volume_step.
Binary search over the integer step index finds the largest affordable
step in O(log n) IPC calls (≈17 for a 99 999-step range vs up to 99 999
in the worst case). Monotonicity of broker margin with volume is assumed,
which holds for standard linear margin schedules.
To stay within the PLR0914 local-variable limit the steps variable is
inlined into hi and the tick temporary is eliminated by accessing the
snapshot dict directly. Error messages still go via msg to satisfy EM102.
Two existing tests are updated to match the binary-search call sequence.
A new regression test (volume_min=0.01, volume_max=1000.0) configures
a tiered-margin mock with its threshold at step 50000 and asserts that
the total order_calc_margin call count does not exceed 25.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: remove obsolete TC003 per-file-ignore for history.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: agent <agent@localhost>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add fetch_latest_closed_rates_indexed and allow_whole_dollar_env opt-in (#43, #44)
Closes#43: add fetch_latest_closed_rates_indexed(client, *, symbol,
granularity, count) -> pd.DataFrame to mt5cli/trading.py. Internally
reuses fetch_latest_closed_rates_for_trading_client(), converts the
"time" column to a UTC-aware DatetimeIndex named "time", and drops the
original column. Exported from trading.__all__, mt5cli.__init__, and
STABLE_SDK_EXPORTS.
Closes#44: extend substitute_env_placeholders() with opt-in
allow_whole_dollar_env=False that expands whole-value $ENV_NAME strings
(entire string must be exactly $IDENTIFIER). Threaded through
build_config(), resolve_account_spec(), and resolve_account_specs() with
the same default=False. Partial strings like "plan$pass", "abc$ENV", or
"$ENV-suffix" are never expanded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: align Markdown table columns in docs and skill file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: treat numeric (float64) epoch seconds as UTC in _rate_time_to_utc
After DataFrame concat or NA upcast the time column becomes float64, which
is still epoch seconds. Using is_numeric_dtype instead of is_integer_dtype
fixes the silent misalignment. Using series.to_numpy() before passing to
pd.to_datetime avoids the redundant pd.DatetimeIndex() wrapper and aligns
with how existing rate-time normalization in schemas.py handles numeric
timestamps.
Add test_converts_float_epoch_seconds_to_utc_datetime_index to cover the
regression. Add a doc note clarifying that build_config cannot expand
login since that parameter is int | None.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: reject NaT values after rate timestamp conversion in _rate_time_to_utc
pd.to_datetime() silently produces NaT for None/NaN inputs rather than
raising, so the function could return a DatetimeIndex containing NaT
despite documenting invalid timestamps as a ValueError. Check any(idx.isna())
after conversion and raise with a clear message.
Add test_raises_on_nat_time_column to cover the regression.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Bump version to v0.9.0
* fix: handle object numeric rate timestamps
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add stable SDK helpers for volume, margin, and closed bars (#39, #40, #41)
Expose generic trading utilities in the stable downstream SDK so applications
like mteor can drop local MT5 adapter code:
- normalize_order_volume() for broker step/min/max sizing
- estimate_order_margin() and calculate_positions_margin() for margin totals
- fetch_latest_closed_rates_for_trading_client() for closed bars from Mt5TradingClient
Update STABLE_SDK_EXPORTS, package-root exports, docs, and unit tests.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* chore: bump version to 0.8.3
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: address PR review feedback on volume cap, rate time, and margin grouping
- Re-apply volume_max after step normalization in normalize_order_volume()
- Drop misleading non-time index reset branch in _ensure_rate_time_column()
- Group positions by (symbol, side) before margin estimation
- Add branch-coverage tests for tick price validation and volume cap edge case
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: address remaining PR review threads on docs and DatetimeIndex
- Rename unnamed DatetimeIndex column to time after reset_index()
- Guard estimate_order_margin example on positive normalized volume
- Document calculate_positions_margin skip vs error propagation behavior
- Add test for unnamed DatetimeIndex branch coverage
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: harden stable SDK margin, rate fetch, and volume normalization
- Wrap order_calc_margin conversion and reject None/non-numeric results
- Validate fetched rate objects are DataFrames before time normalization
- Return 0.0 for non-finite volume inputs and constraints in normalize_order_volume
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: reject non-finite volumes in margin estimation helpers
Use _is_positive_finite_number() in estimate_order_margin() and
calculate_positions_margin() so NaN/inf volumes never reach broker calls.
Add focused tests and document non-finite volume skipping in trading.md.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: guard symbol filter in calculate_positions_margin for empty frames
Return 0.0 before filtering when positions are empty or lack a symbol column.
Add regression tests for filtered calls on malformed position frames.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* feat: add injectable update_backend to ThrottledHistoryUpdater
Allow downstream applications to substitute the history update backend via
the ThrottledHistoryUpdater constructor without monkey-patching
mt5cli.sdk.update_history. Defaults to update_history for backward
compatibility.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* chore: fix lint and format after QA
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* chore: bump version to 0.8.2
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: use explicit None check for ThrottledHistoryUpdater backend
Only None selects the default update_history backend so falsy callable
objects with __bool__ returning False are preserved as custom backends.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* feat: add stable MT5Client public API and infrastructure layer
Introduce a reusable public API for downstream trading applications:
- MT5Client as the primary client abstraction with order_check/order_send
- schemas module with DataKind contracts, validation, and normalization
- converters, exceptions, retry, and storage facade modules
- CLI order commands now route through MT5Client
- connected_client made public; retry logic centralized
- Contract tests for API surface, schemas, and storage round-trips
- README and docs updated with Python API usage examples
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* fix: correct time coercion, broker-safe symbols, and execution docs
- Normalize MT5 time columns with correct second/millisecond units
- Coerce all present known MT5 time fields, including optional order times
- Preserve broker symbol casing in normalize_symbol()
- Document order_send() as a live execution primitive with clear scope boundaries
- Add contract tests for timestamp and symbol normalization behavior
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* Consolidate duplicated export and history streaming helpers.
Reduce repeated CLI export plumbing, shared per-symbol SQLite writes, and test mock setup without changing public behavior.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Bump version from 0.7.0 to 0.7.1.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Refactor MT5 constant parsing to delegate to pdmt5 >= 0.3.0
Replace local TIMEFRAME_MAP, TICK_FLAG_MAP, and parser helpers with thin
compatibility wrappers around pdmt5. COPY_TICKS flags now use real MT5 values
(ALL=-1, INFO=1, TRADE=2). Click parameter types validate all inputs through
the wrappers. Update tests and docs to describe the pdmt5/mt5cli/mt5api layering.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* Fix timeframe defaults and COPY_TICKS flag defaults after pdmt5 migration
Use short timeframe aliases for default history collection and granularity
naming via pdmt5.get_timeframe_name. Set CLI/SDK default tick flags to ALL
(-1) instead of the legacy mt5cli-only value.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* Address CI lint failure and PR review feedback
Fix ruff import ordering in history.py. Use ALL string defaults for CLI tick
flags, isolate TICK_FLAG_MAP as a dict snapshot, derive flag names from pdmt5,
reuse TIMEFRAME_NAMES for default history timeframes, and add tests for prefix
stripping and TIMEFRAME_ key filtering.
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* Bump version to 0.7.0
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daichi Narushima <dceoy@users.noreply.github.com>
* Add closed-bar rate helpers and bump version to 0.6.0.
Expose drop_forming_rate_bar and multi-account collectors so downstream apps no longer need count+1 fetches and manual bar trimming.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Bump pygments to 2.20.0 to fix CVE-2026-4539 ReDoS advisory.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback on closed-bar rate collection.
Validate count and start_pos before MT5 fetches, avoid redundant frame copies, clarify empty-series errors, and expand test coverage.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Include symbol and timeframe in empty closed-rate error messages.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Guard dedup scopes by written columns
* Address dedup scope review feedback
* Remove legacy dedup scope support
* Remove stale legacy descriptions
* chore: bump version from 0.5.1 to 0.5.2
* Add public helpers to resolve rate compatibility view names.
Expose resolve_rate_view_name and resolve_rate_view_names in mt5cli.history so consumers can derive mt5cli-managed SQLite view names from stored rates metadata without reimplementing the naming rules.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add reusable export, tick-window, and margin helpers for downstream tools.
Expose SQLite append/dedup export, recent tick retrieval, and minimum margin
summary through the SDK and CLI so projects like mteor can depend on mt5cli
instead of duplicating MT5 data plumbing.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Bump version to 0.4.3.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback for rate view resolution and SDK helpers.
Harden SQLite read-only connections, tighten view discovery, improve recent_ticks
fetch efficiency, default SQLite export to append, and expand tests and docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix read-only SQLite URI construction on Windows.
Use Path.as_uri() so encoded file URIs work cross-platform with mode=ro.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Rename sqlite_history module to history.
Drop the sqlite-specific prefix now that history collection is the primary module name across SDK, tests, and docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback for history module rename.
Add a sqlite_history compatibility shim, clarify docs naming, and align the
module docstring with the collect-history SQLite scope.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove sqlite_history compatibility shim.
The rename to mt5cli.history is intentionally breaking; downstream code
should update imports rather than rely on a deprecated re-export path.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add incremental SQLite history SDK for automated pipelines.
Extract sqlite history helpers into a dedicated module and expose update_history APIs that resume from existing MAX(time) values instead of re-fetching fixed date ranges.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix incremental history deals and stale rate view cleanup.
Fetch account events once during incremental updates, drop stale rate_* views when timeframes change, and avoid SQLite variable limits on wide frames.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix incremental deal filtering edge cases
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback for incremental SQLite history.
Make rate views collision-free, batch incremental resume queries, scope deduplication to appended boundaries, validate before opening MT5, use atomic SQLite transactions, and expand docs/tests for the new helpers.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Document collect-history SQLite schema with ER diagram.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix account-event filtering and drop legacy rates resume.
Account events must follow only account_event_start, not per-symbol trade
cursors. Require normalized rates schema and fail fast when timeframe is missing.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Validate normalized rates schema before incremental resume.
Require symbol, timeframe, and time on existing rates tables with clear
ValueError messages, and add regression tests for malformed schemas.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Refactor cli.py into cli and utils modules
Extract constants, enums, Click parameter types, and parse/export utility
functions into a new mt5cli/utils.py module, keeping the typer app, commands,
and collect-history SQLite helpers in cli.py.
https://claude.ai/code/session_016JwSEhPyq6phXySktQ1FGU
* Address review comments
* Add programmatic SDK layer for read-only MT5 data collection.
Expose Mt5CliClient and collect_history through the package API while keeping CLI commands as thin adapters over the SDK.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Harden SDK connection lifecycle and scope internal helpers as private.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Export build_config in the public API and bump version to 0.4.0.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove duplicate scripts/ in favor of local-qa skill script.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add collect-history command for bulk SQLite export
Bundles rates, ticks, history-orders, and history-deals for one or more
symbols into a single SQLite database. Tick collection uses
copy_ticks_range_as_df with a --flags option defaulting to ALL. With
--with-views, optional cash_events and positions_reconstructed views are
derived from history_deals when the required columns are present.
* Extend collect-history with datasets, if-exists, timeframe, view fixes
- Fetch history-orders and history-deals per symbol so --symbol applies
consistently across all four datasets.
- Add repeatable --dataset (rates, ticks, history-orders, history-deals)
so ticks are no longer required and any subset can be collected.
- Add --if-exists append|replace|fail to control SQLite table conflict
behavior instead of hard-coding replace.
- Record the requested timeframe in a timeframe column on the rates
table so appended runs at different timeframes stay distinguishable.
- Fix positions_reconstructed to exclude positions with no closing
deals, use volume-weighted open/close prices, and report reversal
deals (DEAL_ENTRY_INOUT) via volume_reversal / reversal_count without
contributing to weighted prices.
- Update tests, README, docs, and skill to match.
* Address collect-history review feedback
* Stream collect-history writes per symbol
* Address PR cleanup for collect-history
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add CLI commands for remaining pdmt5.dataframe methods
Add the following subcommands so the CLI fully covers pdmt5.dataframe's
public *_as_df methods:
- version
- last-error
- symbol-info-tick
- market-book
- order-check (request via inline JSON or @path/to/file.json)
- order-send (request via inline JSON or @path/to/file.json)
Also export a new parse_request helper for parsing JSON order requests,
add tests for every new command, and update the README and docs command
tables.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Bump version to 0.2.0
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* Address PR review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Harden CLI error assertions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Add MkDocs and related dependencies (mkdocs-material, mkdocstrings,
pymdown-extensions) to dev dependencies. Update CI workflow to use
Material theme for documentation deployment.
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
- Add pyarrow dependency for parquet export support
- Add docstring to tests/__init__.py (ruff D104)
- Disable reportMissingTypeStubs for pdmt5 in pyright config
- Exclude __main__.py from coverage measurement
- Format markdown tables with prettier
- Add uv.lock
https://claude.ai/code/session_01YW3YHru8wRH9dvHnBX7xf1
Create a standalone CLI package that uses pdmt5 as a dependency to export
MetaTrader 5 data to CSV, JSON, Parquet, and SQLite3 formats. Includes
12 subcommands for rates, ticks, account/terminal info, symbols, orders,
positions, and trading history, along with comprehensive test coverage.
https://claude.ai/code/session_01YW3YHru8wRH9dvHnBX7xf1