feat: add fetch_recent_history_deals_for_trading_client to stable SDK (#90)

* refactor: collapse repeated tests with pytest.mark.parametrize

Collapse 13 near-identical test methods into 4 parametrized tests
across test_cli.py and test_sdk.py, keeping all 1045 cases passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add fetch_recent_history_deals_for_trading_client to stable SDK

Adds a generic history deal retrieval helper for active trading clients,
a _HistoryDealsClientProtocol describing the minimal required interface,
clarified create_trading_client() docs (returns pdmt5.Mt5DataClient, not
MT5Client), 9 unit tests at 100% coverage, and updated trading.md and
public-contract.md with examples and out-of-scope strategy semantics note.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: narrow Mt5CliClient protocol claim and preserve empty deal DataFrame schema

- _HistoryDealsClientProtocol docstring and fetch_recent_history_deals_for_trading_client
  docstring now explicitly state that Mt5CliClient (mt5_session) exposes
  history_deals() not history_deals_get_as_df() and does not satisfy the protocol;
  the function is for trading-client sessions (pdmt5.Mt5DataClient) only
- Empty DataFrames with columns are now passed through with reset_index rather
  than replaced by a bare pd.DataFrame(), preserving schema for callers that rely
  on stable column names even in no-deal windows
- Tests updated to assert schema preservation on empty results and bare empty on None

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: add combined protocol so create_trading_client() is type-safe with history deals helper

Adds _TradingHistoryDealsClientProtocol combining _Mt5ClientProtocol and
_HistoryDealsClientProtocol, and updates create_trading_client() and
mt5_trading_session() to return/yield this combined type so the natural SDK
flow `client = create_trading_client(...); fetch_recent_history_deals_for_trading_client(client)`
is type-safe under pyright strict without casts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: validate hours is finite before timedelta in fetch_recent_history_deals_for_trading_client

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Bump version to 1.1.1

---------

Co-authored-by: agent <agent@localhost>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Daichi Narushima
2026-06-30 05:28:34 +09:00
committed by GitHub
parent 1ffac45d57
commit 513eb7617d
10 changed files with 434 additions and 195 deletions
+5 -1
View File
@@ -45,7 +45,7 @@ These names are exported from `mt5cli` and enumerated in
| `MT5Client` | Read-only data client with optional `order_check` / `order_send` |
| `build_config` | Build `pdmt5.Mt5Config` 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` |
| `mt5_session` | Context manager: initialize, login, yield client, shutdown |
| `create_trading_client`, `mt5_trading_session` | Trading-capable MT5 client lifecycle; returns a client supporting order execution and account management |
| `create_trading_client`, `mt5_trading_session` | Trading-capable MT5 client lifecycle; returns a raw `pdmt5.Mt5DataClient` (not `MT5Client`) supporting order execution, account management, and history deal retrieval |
| `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` |
@@ -99,6 +99,7 @@ strategy entries, exits, Kelly sizing, or signal logic.
| `determine_order_limits` | SL/TP price levels from ratios |
| `calculate_trailing_stop_updates` | Per-ticket generic trailing stop-loss update plan |
| `ensure_symbol_selected` | Select/verify Market Watch visibility |
| `fetch_recent_history_deals_for_trading_client` | Recent deal history from a connected trading client |
| `place_market_order`, `close_open_positions`, `update_sltp_for_open_positions`, `update_trailing_stop_loss_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 |
@@ -254,6 +255,9 @@ The following belong in consuming applications, not in mt5cli:
- 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
- Entry-deal classification, Kelly fractions, or betting-specific deal transformations
(use `fetch_recent_history_deals_for_trading_client` to retrieve raw deal data, then
apply downstream transformations in your own adapter layer)
- Application-specific credential schema keys wired into mt5cli internals
mt5cli provides connection lifecycle, normalized data access, SQLite history
+55
View File
@@ -10,6 +10,11 @@ client supporting order execution and account management, use `Mt5Config.path`
to launch the terminal when configured, and `mt5_trading_session()` always
calls `shutdown()` on exit.
`create_trading_client()` returns a raw `pdmt5.Mt5DataClient` instance, not the
higher-level `MT5Client` wrapper. Use `mt5_session()` / `MT5Client` for
read-only data collection; use `mt5_trading_session()` only where order
placement or trading calculations are required.
```python
from mt5cli import create_trading_client, mt5_trading_session
@@ -182,6 +187,55 @@ updates: list[OrderExecutionResult] = update_sltp_for_open_positions(
Closes issue #33: strategy-neutral order planning and execution helpers exposed
through the stable package root without embedding entry/exit policy.
## Retrieving recent history deals
`fetch_recent_history_deals_for_trading_client()` fetches history deals from an
already-connected trading client over a trailing time window. It works directly
with the object returned by `create_trading_client()` (a raw
`pdmt5.Mt5DataClient`) without requiring any additional wrapping.
The helper returns a chronologically sorted DataFrame with a `RangeIndex` and
all columns from the underlying client (`time`, `symbol`, `type`, `entry`,
`volume`, `profit`, `position_id`, etc.). It does **not** apply any
strategy-specific transformations — entry/exit classification, Kelly fractions,
and betting semantics belong in downstream applications.
```python
from mt5cli import (
create_trading_client,
fetch_recent_history_deals_for_trading_client,
)
client = create_trading_client(login=12345, server="Broker-Demo")
try:
deals_df = fetch_recent_history_deals_for_trading_client(
client,
symbol="JP225",
hours=24,
)
finally:
client.shutdown()
```
Or inside a managed session:
```python
from mt5cli import fetch_recent_history_deals_for_trading_client, mt5_trading_session
with mt5_trading_session(login=12345, server="Broker-Demo") as client:
deals_df = fetch_recent_history_deals_for_trading_client(
client,
symbol="JP225",
hours=48,
)
```
`hours` must be positive; `date_to` defaults to `datetime.now(UTC)`. An empty
or `None` result from the underlying client is normalized to an empty DataFrame.
Downstream packages own all strategy-specific transformations. mt5cli does not
provide entry-deal classification, Kelly sizing, or any betting-specific helpers.
## Migration from application-local helpers
| Application-local concern | mt5cli replacement |
@@ -192,6 +246,7 @@ through the stable package root without embedding entry/exit policy.
| Local broker volume step normalization | `normalize_order_volume()` |
| Local order or position margin estimation | `estimate_order_margin()`, `calculate_positions_margin()` |
| Local closed-bar fetch from a trading session | `fetch_latest_closed_rates_for_trading_client()`, `fetch_latest_closed_rates_indexed()` |
| Local recent deal history fetch from a trading session | `fetch_recent_history_deals_for_trading_client()` |
| Local SL/TP price derivation | `determine_order_limits()` |
| Throttled SQLite history loop with ad-hoc error handling | `ThrottledHistoryUpdater(suppress_errors=True)` |