Files
mt5cli/docs/api/public-contract.md
T
Daichi Narushima 82a39731ed feat: add fetch_latest_closed_rates_indexed and allow_whole_dollar_env opt-in (#45)
* 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>
2026-06-22 22:52:19 +09:00

14 KiB

Public API Contract

mt5cli is the generic MT5 data and execution infrastructure layer for downstream Python applications. The intended dependency direction is:

downstream app -> mt5cli -> pdmt5 -> MetaTrader 5

Downstream packages should import from the package root (from mt5cli import ...) and treat the symbols listed below as the stable SDK contract. CLI commands mirror the same behavior but are not importable Python APIs.

Stable downstream SDK API

These names are exported from mt5cli and covered by the contract in mt5cli.STABLE_SDK_EXPORTS (defined in mt5cli.contract). Prefer MT5Client over the legacy Mt5CliClient alias for new code.

Session lifecycle and configuration

Symbol Role
MT5Client, Mt5CliClient Read-only data client with optional order_check / order_send
build_config Build pdmt5.Mt5Config from connection fields
mt5_session Context manager: initialize, login, yield client, shutdown
create_trading_client, mt5_trading_session Trading-capable pdmt5.Mt5TradingClient lifecycle
AccountSpec Generic account group: symbols plus optional credentials
resolve_account_spec, resolve_account_specs Merge overrides and expand ${ENV_VAR} placeholders; opt-in allow_whole_dollar_env for bare $NAME
substitute_env_placeholders Replace ${NAME} substrings from the environment; opt-in allow_whole_dollar_env for whole-value $NAME

Credential resolution is generic: any environment variable name may appear inside ${...}. mt5cli does not hard-code application-specific keys such as mt5_login or mt5_exe.

Pass allow_whole_dollar_env=True to substitute_env_placeholders(), resolve_account_spec(), resolve_account_specs(), and build_config() to additionally expand strings whose entire value is a bare $ENV_NAME identifier. Partial strings such as "plan$pass", "abc$ENV", or "$ENV-suffix" are never expanded — only an exact $IDENTIFIER whole-string match qualifies. Default is False to preserve backward compatibility.

Read-only MT5 data access

Module-level helpers open a transient connection per call. Prefer mt5_session or MT5Client when making many requests in one process.

Area Symbols
Rates copy_rates_from, copy_rates_from_pos, copy_rates_range, latest_rates, collect_latest_rates
Ticks copy_ticks_from, copy_ticks_range, recent_ticks
Account / terminal account_info, terminal_info, mt5_version, last_error, mt5_summary, mt5_summary_as_df
Symbols / market symbols, symbol_info, symbol_info_tick, market_book, minimum_margins
Trading state (read) orders, positions, history_orders, history_deals, recent_history_deals

Use mt5_version for MetaTrader 5 terminal version data. The name version at the package root refers to importlib.metadata.version (package metadata), not the MT5 SDK helper.

Closed-bar rate helpers

MetaTrader 5 returns the still-forming bar as the last row when start_pos=0. Use these helpers instead of reimplementing bar trimming or timestamp normalization in downstream apps.

Symbol Role
drop_forming_rate_bar Remove the last row from chronologically ordered rate data
fetch_latest_closed_rates Single connected client: fetch count + 1, drop forming bar
fetch_latest_closed_rates_for_trading_client Closed bars from an active Mt5TradingClient session; returns RangeIndex
fetch_latest_closed_rates_indexed Same as above but returns a UTC DatetimeIndex named "time" (no time column)
collect_latest_closed_rates_for_accounts Multi-account closed bars with optional retry wrapper
collect_latest_closed_rates_by_granularity Same data keyed by (symbol, granularity_name)
collect_latest_rates_for_accounts Latest bars including the forming bar when start_pos=0
collect_latest_rates_for_accounts_with_retries Bounded exponential backoff for transient MT5 errors

SQLite history collection and rate loading

Symbol Role
collect_history One-shot date-range export into SQLite
update_history, update_history_with_config Incremental append from MAX(time) cursors
ThrottledHistoryUpdater Minimum interval between successful incremental updates; optional update_backend injection
resolve_history_datasets, resolve_history_timeframes, resolve_history_tick_flags History pipeline configuration
build_rate_view_name, resolve_rate_table_name, resolve_rate_view_name, resolve_rate_view_names, resolve_rate_tables Map symbols/timeframes to mt5cli-managed table or view names
RateTarget, build_rate_targets Neutral (symbol, timeframe) series descriptors
load_rate_data, load_rate_data_from_connection Load one table/view into a time-indexed DataFrame
load_rate_series_from_sqlite, load_rate_series_by_granularity Load one or many series; fail clearly when managed views are missing

Pass require_existing=True to rate view resolution helpers when downstream code must fail instead of receiving a best-guess view name. Multi-series loaders require existing managed rate_*__* views unless explicit_tables is supplied.

See History Collection (SQLite) for schema, view naming, and ER diagrams.

Trading and sizing primitives (generic)

These helpers implement broker-facing calculations only. They do not encode strategy entries, exits, Kelly sizing, or signal logic.

Symbol Role
get_account_snapshot, get_symbol_snapshot, get_tick_snapshot, get_positions_frame Normalized account/symbol/tick/position views
detect_position_side Net long / short / flat from open positions
calculate_spread_ratio Relative bid-ask spread
calculate_margin_and_volume, calculate_volume_by_margin, calculate_new_position_margin_ratio Margin budget and volume sizing
normalize_order_volume, estimate_order_margin, calculate_positions_margin Broker volume normalization and margin totals
determine_order_limits SL/TP price levels from ratios
ensure_symbol_selected Select/verify Market Watch visibility
place_market_order, close_open_positions, update_sltp_for_open_positions Order execution helpers (dry_run supported)
MarginVolume, OrderLimits, OrderExecutionResult Typed return contracts for order helpers
OrderSide, OrderFillingMode, OrderTimeMode, PositionSide, ExecutionStatus Typed enums for order helpers

MT5Client.order_send() and CLI order-send --yes are live execution paths.

Order helpers validate broker stop-level distance in determine_order_limits() and raise Mt5TradingError when computed SL/TP prices are too close to the entry quote. Validation uses trade_stops_level * point from the current quote and symbol metadata as a pre-check only; it does not guarantee live order acceptance after price movement and does not inspect trade_freeze_level. Live place_market_order() and SL/TP updates call ensure_symbol_selected() so hidden symbols are added to Market Watch before sending requests. Failed, malformed, or unknown broker retcodes are fail-closed and returned as status="failed" with normalized request / response details; dry_run=True never calls ensure_symbol_selected() or order_send().

Errors and MT5 type re-exports

Symbol Role
Mt5CliError, Mt5ConnectionError, Mt5OperationError, Mt5SchemaError Stable mt5cli exception types
normalize_mt5_exception, call_with_normalized_errors, is_recoverable_mt5_error Error normalization and retry classification
Mt5Config, Mt5RuntimeError, Mt5TradingClient, Mt5TradingError Re-exported pdmt5 types for adapter convenience

Additional public exports (secondary)

The package root also exports schema, storage, and parsing helpers (for example DataKind, Dataset, normalize_dataframe, export_dataframe, parse_timeframe, TIMEFRAME_MAP). These are public but oriented toward export pipelines and advanced integration. Prefer the stable symbols above for core infrastructure.

CLI commands

The Typer application in mt5cli.cli exposes file-export commands documented in CLI Module and the project README. CLI commands:

  • Require -o/--output and write CSV, JSON, Parquet, or SQLite.
  • Accept global MT5 connection options (--login, --password, --server, --path, --timeout).
  • Delegate to the same Python APIs described here; they are not duplicated business logic.

order-send requires --yes before placing live trades.

Internal helpers (not stable)

Do not import these for downstream contracts; they may change without a semver notice:

Module Examples
mt5cli.sdk connected_client, _run_with_client, private coercion helpers
mt5cli.history write_*_dataset, deduplicate_history_tables, parse_sqlite_timestamp
mt5cli.retry retry_with_backoff
mt5cli.cli Typer command handlers and Click parameter types
Leading-underscore names Any _-prefixed function or method

Use the package-root stable exports instead of reaching into submodule internals.

Explicitly out of scope

mt5cli must not implement downstream strategy or research responsibilities. The following belong in consuming applications, not in mt5cli:

  • Signal detection (for example AR-GARCH or other model-specific triggers)
  • Backtesting, walk-forward analysis, or parameter optimization
  • Strategy-specific risk policy, position sizing systems, or Kelly fractions
  • Entry/exit decision logic or YAML strategy semantics
  • Application-specific credential schema keys wired into mt5cli internals

mt5cli provides connection lifecycle, normalized data access, SQLite history machinery, closed-bar helpers, generic margin/volume/spread/SL/TP utilities, and optional order primitives so downstream apps can focus on strategy code behind their own adapter layer.

Contract verification

tests/test_contracts.py asserts that every name in STABLE_SDK_EXPORTS is importable from mt5cli, documents key closed-bar, rate-view, SQLite loading, account-resolution, and trading-session behaviors, and keeps the contract set aligned with __all__.