mt5cli 1.0.0__tar.gz → 1.0.1__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.0.0 → mt5cli-1.0.1}/PKG-INFO +1 -1
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/index.md +25 -13
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/cli.py +41 -30
- {mt5cli-1.0.0 → mt5cli-1.0.1}/pyproject.toml +1 -1
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_cli.py +60 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/uv.lock +1 -1
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.agents/skills/local-qa/SKILL.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.agents/skills/local-qa/scripts/qa.sh +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.agents/skills/mt5cli/SKILL.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.agents/skills/pr-feedback-triage/SKILL.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.claude/agents/codex.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.claude/settings.json +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/FUNDING.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/dependabot.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/renovate.json +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/workflows/ci.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/workflows/claude.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.github/workflows/release.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/.gitignore +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/AGENTS.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/CLAUDE.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/LICENSE +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/README.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/cli.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/client.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/converters.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/exceptions.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/history.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/index.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/public-contract.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/schemas.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/sdk.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/trading.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/docs/api/utils.md +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mkdocs.yml +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/__init__.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/__main__.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/client.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/contract.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/converters.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/exceptions.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/history.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/retry.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/schemas.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/sdk.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/trading.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/mt5cli/utils.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/__init__.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/conftest.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_contracts.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_history.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_sdk.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_trading.py +0 -0
- {mt5cli-1.0.0 → mt5cli-1.0.1}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mt5cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
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>
|
|
@@ -147,20 +147,32 @@ mt5cli --login 12345 --password mypass --server MyBroker-Demo \
|
|
|
147
147
|
| `minimum-margins` | Export minimum-volume margin summary |
|
|
148
148
|
| `market-book` | Export market depth (order book) |
|
|
149
149
|
|
|
150
|
-
### Trading
|
|
150
|
+
### Trading State
|
|
151
151
|
|
|
152
|
-
| Command | Description
|
|
153
|
-
| ---------------------- |
|
|
154
|
-
| `orders` | Export active orders
|
|
155
|
-
| `positions` | Export open positions
|
|
156
|
-
| `history-orders` | Export historical orders
|
|
157
|
-
| `history-deals` | Export historical deals
|
|
158
|
-
| `recent-history-deals` | Export historical deals from a trailing window
|
|
159
|
-
| `mt5-summary` | Export terminal/account status summary
|
|
160
|
-
| `order-check` | Check funds sufficiency for a trade request
|
|
161
|
-
| `order-send` | Send a trade request to the trade server (`--yes` required) |
|
|
152
|
+
| Command | Description |
|
|
153
|
+
| ---------------------- | --------------------------------------------------------------------- |
|
|
154
|
+
| `orders` | Export active orders |
|
|
155
|
+
| `positions` | Export open positions |
|
|
156
|
+
| `history-orders` | Export historical orders |
|
|
157
|
+
| `history-deals` | Export historical deals |
|
|
158
|
+
| `recent-history-deals` | Export historical deals from a trailing window |
|
|
159
|
+
| `mt5-summary` | Export terminal/account status summary |
|
|
160
|
+
| `order-check` | Check funds sufficiency for a trade request (read-only, no `--yes`) |
|
|
162
161
|
|
|
163
|
-
|
|
162
|
+
### Execution (live / mutating)
|
|
163
|
+
|
|
164
|
+
These commands send requests to the live trade server and can place or close
|
|
165
|
+
real trades. Both require `--yes` for live execution.
|
|
166
|
+
|
|
167
|
+
| Command | Description |
|
|
168
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------- |
|
|
169
|
+
| `order-send` | Send a **raw** trade request directly to MT5 (`--yes` required; expert path — no extra validation) |
|
|
170
|
+
| `close-positions` | Close open positions by `--symbol` or `--ticket` (`--yes` required for live; `--dry-run` to preview) |
|
|
171
|
+
|
|
172
|
+
Use `order-check` (Trading State) to validate funds before running `order-send --yes`.
|
|
173
|
+
`close-positions` is the safer high-level alternative that builds correct close
|
|
174
|
+
requests automatically. `order-send` is the expert raw path — downstream
|
|
175
|
+
applications should prefer dedicated closing helpers or their own risk controls.
|
|
164
176
|
|
|
165
177
|
### Bulk Collection
|
|
166
178
|
|
|
@@ -217,7 +229,7 @@ See the [History schema diagram](api/history.md#entity-relationship-diagram) for
|
|
|
217
229
|
|
|
218
230
|
Browse the API documentation for detailed module information:
|
|
219
231
|
|
|
220
|
-
- [CLI Module](api/cli.md) - CLI application with export commands
|
|
232
|
+
- [CLI Module](api/cli.md) - CLI application with data export and execution commands
|
|
221
233
|
- [SDK Module](api/sdk.md) - Programmatic read-only data collection API
|
|
222
234
|
- [Utils Module](api/utils.md) - Constants, parameter types, parsers, and export utilities
|
|
223
235
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Command-line interface for MetaTrader 5 data
|
|
1
|
+
"""Command-line interface for MetaTrader 5 data and execution utilities."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -55,7 +55,12 @@ class _ExportContext:
|
|
|
55
55
|
|
|
56
56
|
app = typer.Typer(
|
|
57
57
|
name="mt5cli",
|
|
58
|
-
help=
|
|
58
|
+
help=(
|
|
59
|
+
"MT5 data and execution utilities — read market data, inspect account"
|
|
60
|
+
" state, and send trade requests. Data commands write to CSV, JSON,"
|
|
61
|
+
" Parquet, or SQLite3. Execution commands (order-send, close-positions)"
|
|
62
|
+
" require --yes for live mutations."
|
|
63
|
+
),
|
|
59
64
|
)
|
|
60
65
|
|
|
61
66
|
_REQUEST_OPTION_HELP = (
|
|
@@ -151,7 +156,7 @@ def _callback( # pyright: ignore[reportUnusedFunction]
|
|
|
151
156
|
typer.Option("--log-level", help="Logging level."),
|
|
152
157
|
] = LogLevel.WARNING,
|
|
153
158
|
) -> None:
|
|
154
|
-
"""Configure shared
|
|
159
|
+
"""Configure shared connection and output options.
|
|
155
160
|
|
|
156
161
|
Raises:
|
|
157
162
|
typer.BadParameter: If the output format cannot be determined.
|
|
@@ -183,7 +188,7 @@ def _callback( # pyright: ignore[reportUnusedFunction]
|
|
|
183
188
|
# ---------------------------------------------------------------------------
|
|
184
189
|
|
|
185
190
|
|
|
186
|
-
@app.command()
|
|
191
|
+
@app.command(rich_help_panel="Data / Export")
|
|
187
192
|
def rates_from(
|
|
188
193
|
ctx: typer.Context,
|
|
189
194
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -210,7 +215,7 @@ def rates_from(
|
|
|
210
215
|
)
|
|
211
216
|
|
|
212
217
|
|
|
213
|
-
@app.command()
|
|
218
|
+
@app.command(rich_help_panel="Data / Export")
|
|
214
219
|
def rates_from_pos(
|
|
215
220
|
ctx: typer.Context,
|
|
216
221
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -236,7 +241,7 @@ def rates_from_pos(
|
|
|
236
241
|
)
|
|
237
242
|
|
|
238
243
|
|
|
239
|
-
@app.command()
|
|
244
|
+
@app.command(rich_help_panel="Data / Export")
|
|
240
245
|
def latest_rates(
|
|
241
246
|
ctx: typer.Context,
|
|
242
247
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -265,7 +270,7 @@ def latest_rates(
|
|
|
265
270
|
)
|
|
266
271
|
|
|
267
272
|
|
|
268
|
-
@app.command()
|
|
273
|
+
@app.command(rich_help_panel="Data / Export")
|
|
269
274
|
def rates_range(
|
|
270
275
|
ctx: typer.Context,
|
|
271
276
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -292,7 +297,7 @@ def rates_range(
|
|
|
292
297
|
)
|
|
293
298
|
|
|
294
299
|
|
|
295
|
-
@app.command()
|
|
300
|
+
@app.command(rich_help_panel="Data / Export")
|
|
296
301
|
def ticks_from(
|
|
297
302
|
ctx: typer.Context,
|
|
298
303
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -316,7 +321,7 @@ def ticks_from(
|
|
|
316
321
|
)
|
|
317
322
|
|
|
318
323
|
|
|
319
|
-
@app.command()
|
|
324
|
+
@app.command(rich_help_panel="Data / Export")
|
|
320
325
|
def ticks_range(
|
|
321
326
|
ctx: typer.Context,
|
|
322
327
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -340,7 +345,7 @@ def ticks_range(
|
|
|
340
345
|
)
|
|
341
346
|
|
|
342
347
|
|
|
343
|
-
@app.command()
|
|
348
|
+
@app.command(rich_help_panel="Data / Export")
|
|
344
349
|
def ticks_recent(
|
|
345
350
|
ctx: typer.Context,
|
|
346
351
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -377,19 +382,19 @@ def ticks_recent(
|
|
|
377
382
|
)
|
|
378
383
|
|
|
379
384
|
|
|
380
|
-
@app.command()
|
|
385
|
+
@app.command(rich_help_panel="Data / Export")
|
|
381
386
|
def account_info(ctx: typer.Context) -> None:
|
|
382
387
|
"""Export account information."""
|
|
383
388
|
_export_command(ctx, lambda client: client.account_info())
|
|
384
389
|
|
|
385
390
|
|
|
386
|
-
@app.command()
|
|
391
|
+
@app.command(rich_help_panel="Data / Export")
|
|
387
392
|
def terminal_info(ctx: typer.Context) -> None:
|
|
388
393
|
"""Export terminal information."""
|
|
389
394
|
_export_command(ctx, lambda client: client.terminal_info())
|
|
390
395
|
|
|
391
396
|
|
|
392
|
-
@app.command()
|
|
397
|
+
@app.command(rich_help_panel="Data / Export")
|
|
393
398
|
def symbols(
|
|
394
399
|
ctx: typer.Context,
|
|
395
400
|
group: Annotated[
|
|
@@ -401,7 +406,7 @@ def symbols(
|
|
|
401
406
|
_export_command(ctx, lambda client: client.symbols(group=group))
|
|
402
407
|
|
|
403
408
|
|
|
404
|
-
@app.command()
|
|
409
|
+
@app.command(rich_help_panel="Data / Export")
|
|
405
410
|
def symbol_info(
|
|
406
411
|
ctx: typer.Context,
|
|
407
412
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -410,7 +415,7 @@ def symbol_info(
|
|
|
410
415
|
_export_command(ctx, lambda client: client.symbol_info(symbol))
|
|
411
416
|
|
|
412
417
|
|
|
413
|
-
@app.command()
|
|
418
|
+
@app.command(rich_help_panel="Data / Export")
|
|
414
419
|
def minimum_margins(
|
|
415
420
|
ctx: typer.Context,
|
|
416
421
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -419,7 +424,7 @@ def minimum_margins(
|
|
|
419
424
|
_export_command(ctx, lambda client: client.minimum_margins(symbol))
|
|
420
425
|
|
|
421
426
|
|
|
422
|
-
@app.command()
|
|
427
|
+
@app.command(rich_help_panel="Data / Export")
|
|
423
428
|
def orders(
|
|
424
429
|
ctx: typer.Context,
|
|
425
430
|
symbol: Annotated[str | None, typer.Option(help="Symbol filter.")] = None,
|
|
@@ -433,7 +438,7 @@ def orders(
|
|
|
433
438
|
)
|
|
434
439
|
|
|
435
440
|
|
|
436
|
-
@app.command()
|
|
441
|
+
@app.command(rich_help_panel="Data / Export")
|
|
437
442
|
def positions(
|
|
438
443
|
ctx: typer.Context,
|
|
439
444
|
symbol: Annotated[str | None, typer.Option(help="Symbol filter.")] = None,
|
|
@@ -447,7 +452,7 @@ def positions(
|
|
|
447
452
|
)
|
|
448
453
|
|
|
449
454
|
|
|
450
|
-
@app.command()
|
|
455
|
+
@app.command(rich_help_panel="Data / Export")
|
|
451
456
|
def history_orders(
|
|
452
457
|
ctx: typer.Context,
|
|
453
458
|
date_from: Annotated[
|
|
@@ -477,7 +482,7 @@ def history_orders(
|
|
|
477
482
|
)
|
|
478
483
|
|
|
479
484
|
|
|
480
|
-
@app.command()
|
|
485
|
+
@app.command(rich_help_panel="Data / Export")
|
|
481
486
|
def history_deals(
|
|
482
487
|
ctx: typer.Context,
|
|
483
488
|
date_from: Annotated[
|
|
@@ -507,7 +512,7 @@ def history_deals(
|
|
|
507
512
|
)
|
|
508
513
|
|
|
509
514
|
|
|
510
|
-
@app.command()
|
|
515
|
+
@app.command(rich_help_panel="Data / Export")
|
|
511
516
|
def recent_history_deals(
|
|
512
517
|
ctx: typer.Context,
|
|
513
518
|
hours: Annotated[float, typer.Option(help="Lookback window in hours.")],
|
|
@@ -530,25 +535,25 @@ def recent_history_deals(
|
|
|
530
535
|
)
|
|
531
536
|
|
|
532
537
|
|
|
533
|
-
@app.command()
|
|
538
|
+
@app.command(rich_help_panel="Data / Export")
|
|
534
539
|
def mt5_summary(ctx: typer.Context) -> None:
|
|
535
540
|
"""Export a compact terminal/account status summary."""
|
|
536
541
|
_export_command(ctx, lambda client: client.mt5_summary_as_df())
|
|
537
542
|
|
|
538
543
|
|
|
539
|
-
@app.command()
|
|
544
|
+
@app.command(rich_help_panel="Data / Export")
|
|
540
545
|
def version(ctx: typer.Context) -> None:
|
|
541
546
|
"""Export MetaTrader5 version information."""
|
|
542
547
|
_export_command(ctx, lambda client: client.version())
|
|
543
548
|
|
|
544
549
|
|
|
545
|
-
@app.command()
|
|
550
|
+
@app.command(rich_help_panel="Data / Export")
|
|
546
551
|
def last_error(ctx: typer.Context) -> None:
|
|
547
552
|
"""Export the last error information."""
|
|
548
553
|
_export_command(ctx, lambda client: client.last_error())
|
|
549
554
|
|
|
550
555
|
|
|
551
|
-
@app.command()
|
|
556
|
+
@app.command(rich_help_panel="Data / Export")
|
|
552
557
|
def symbol_info_tick(
|
|
553
558
|
ctx: typer.Context,
|
|
554
559
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -557,7 +562,7 @@ def symbol_info_tick(
|
|
|
557
562
|
_export_command(ctx, lambda client: client.symbol_info_tick(symbol))
|
|
558
563
|
|
|
559
564
|
|
|
560
|
-
@app.command()
|
|
565
|
+
@app.command(rich_help_panel="Data / Export")
|
|
561
566
|
def market_book(
|
|
562
567
|
ctx: typer.Context,
|
|
563
568
|
symbol: Annotated[str, typer.Option(help="Symbol name.")],
|
|
@@ -566,7 +571,7 @@ def market_book(
|
|
|
566
571
|
_export_command(ctx, lambda client: client.market_book(symbol))
|
|
567
572
|
|
|
568
573
|
|
|
569
|
-
@app.command()
|
|
574
|
+
@app.command(rich_help_panel="Data / Export")
|
|
570
575
|
def order_check(
|
|
571
576
|
ctx: typer.Context,
|
|
572
577
|
request: Annotated[
|
|
@@ -578,7 +583,7 @@ def order_check(
|
|
|
578
583
|
_export_command(ctx, lambda client: client.order_check(request))
|
|
579
584
|
|
|
580
585
|
|
|
581
|
-
@app.command()
|
|
586
|
+
@app.command(rich_help_panel="Execution")
|
|
582
587
|
def order_send(
|
|
583
588
|
ctx: typer.Context,
|
|
584
589
|
request: Annotated[
|
|
@@ -590,7 +595,13 @@ def order_send(
|
|
|
590
595
|
typer.Option("--yes", help="Confirm the live trade request."),
|
|
591
596
|
] = False,
|
|
592
597
|
) -> None:
|
|
593
|
-
"""Send a
|
|
598
|
+
"""Send a raw trade request to the trade server (expert path, live execution).
|
|
599
|
+
|
|
600
|
+
Passes the request JSON directly to MT5 ``order_send``. This is the
|
|
601
|
+
low-level expert path — it places real trades on the connected account
|
|
602
|
+
with no additional validation beyond what MT5 itself performs. Use
|
|
603
|
+
``order-check`` first to validate funds sufficiency. Prefer
|
|
604
|
+
``close-positions`` for closing open positions. ``--yes`` is required.
|
|
594
605
|
|
|
595
606
|
Raises:
|
|
596
607
|
typer.BadParameter: If --yes is not provided.
|
|
@@ -628,7 +639,7 @@ def _execution_results_to_df(results: list[OrderExecutionResult]) -> pd.DataFram
|
|
|
628
639
|
return pd.DataFrame(rows)
|
|
629
640
|
|
|
630
641
|
|
|
631
|
-
@app.command()
|
|
642
|
+
@app.command(rich_help_panel="Execution")
|
|
632
643
|
def close_positions(
|
|
633
644
|
ctx: typer.Context,
|
|
634
645
|
symbol: Annotated[
|
|
@@ -691,7 +702,7 @@ def close_positions(
|
|
|
691
702
|
_execute_export(ctx, lambda: df)
|
|
692
703
|
|
|
693
704
|
|
|
694
|
-
@app.command()
|
|
705
|
+
@app.command(rich_help_panel="Collection")
|
|
695
706
|
def collect_history(
|
|
696
707
|
ctx: typer.Context,
|
|
697
708
|
symbol: Annotated[
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mt5cli"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.1"
|
|
4
4
|
description = "Generic MT5 data and execution infrastructure for Python applications"
|
|
5
5
|
authors = [{name = "dceoy", email = "dceoy@users.noreply.github.com"}]
|
|
6
6
|
maintainers = [{name = "dceoy", email = "dceoy@users.noreply.github.com"}]
|
|
@@ -740,6 +740,66 @@ class TestCommands:
|
|
|
740
740
|
assert "must be a JSON object" in normalize_cli_output(result.output)
|
|
741
741
|
|
|
742
742
|
|
|
743
|
+
# ---------------------------------------------------------------------------
|
|
744
|
+
# Help text / scope tests
|
|
745
|
+
# ---------------------------------------------------------------------------
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
class TestHelpText:
|
|
749
|
+
"""Tests verifying CLI help text matches the documented scope."""
|
|
750
|
+
|
|
751
|
+
def test_top_level_help_mentions_execution(self) -> None:
|
|
752
|
+
"""Top-level help must describe execution utilities, not export only."""
|
|
753
|
+
result = runner.invoke(app, ["--help"])
|
|
754
|
+
assert result.exit_code == 0
|
|
755
|
+
output = normalize_cli_output(result.output)
|
|
756
|
+
assert "execution" in output.lower()
|
|
757
|
+
|
|
758
|
+
def test_top_level_help_has_execution_panel(self) -> None:
|
|
759
|
+
"""Top-level help must show an Execution command group."""
|
|
760
|
+
result = runner.invoke(app, ["--help"])
|
|
761
|
+
assert result.exit_code == 0
|
|
762
|
+
assert "Execution" in result.output
|
|
763
|
+
|
|
764
|
+
def test_top_level_help_has_data_export_panel(self) -> None:
|
|
765
|
+
"""Top-level help must show a Data / Export command group."""
|
|
766
|
+
result = runner.invoke(app, ["--help"])
|
|
767
|
+
assert result.exit_code == 0
|
|
768
|
+
assert "Data / Export" in result.output
|
|
769
|
+
|
|
770
|
+
def test_order_send_help_mentions_expert_and_raw(self) -> None:
|
|
771
|
+
"""order-send help must communicate it is the expert raw-request path."""
|
|
772
|
+
result2 = runner.invoke(
|
|
773
|
+
app,
|
|
774
|
+
["-o", "out.csv", "order-send", "--help"],
|
|
775
|
+
)
|
|
776
|
+
assert result2.exit_code == 0
|
|
777
|
+
output = normalize_cli_output(result2.output)
|
|
778
|
+
assert "raw" in output.lower()
|
|
779
|
+
assert "expert" in output.lower()
|
|
780
|
+
|
|
781
|
+
def test_order_send_help_mentions_live_execution(self) -> None:
|
|
782
|
+
"""order-send help must warn about live execution."""
|
|
783
|
+
result = runner.invoke(
|
|
784
|
+
app,
|
|
785
|
+
["-o", "out.csv", "order-send", "--help"],
|
|
786
|
+
)
|
|
787
|
+
assert result.exit_code == 0
|
|
788
|
+
output = normalize_cli_output(result.output)
|
|
789
|
+
assert "live" in output.lower()
|
|
790
|
+
|
|
791
|
+
def test_close_positions_help_mentions_dry_run_and_yes(self) -> None:
|
|
792
|
+
"""close-positions help must document both safety gates."""
|
|
793
|
+
result = runner.invoke(
|
|
794
|
+
app,
|
|
795
|
+
["-o", "out.csv", "close-positions", "--help"],
|
|
796
|
+
)
|
|
797
|
+
assert result.exit_code == 0
|
|
798
|
+
output = normalize_cli_output(result.output)
|
|
799
|
+
assert "--dry-run" in output
|
|
800
|
+
assert "--yes" in output
|
|
801
|
+
|
|
802
|
+
|
|
743
803
|
# ---------------------------------------------------------------------------
|
|
744
804
|
# close-positions command
|
|
745
805
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|