hypertrader 0.1.9__tar.gz → 0.2.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.
Files changed (49) hide show
  1. {hypertrader-0.1.9 → hypertrader-0.2.1}/PKG-INFO +23 -1
  2. {hypertrader-0.1.9 → hypertrader-0.2.1}/README.md +22 -0
  3. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/PKG-INFO +23 -1
  4. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/SOURCES.txt +7 -0
  5. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.py +32 -23
  6. {hypertrader-0.1.9 → hypertrader-0.2.1}/modes/auto_trader.py +164 -45
  7. {hypertrader-0.1.9 → hypertrader-0.2.1}/modes/position_management.py +85 -24
  8. {hypertrader-0.1.9 → hypertrader-0.2.1}/setup.py +1 -1
  9. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/base.py +31 -1
  10. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/fib_reversal.py +6 -0
  11. hypertrader-0.2.1/tests/test_api_retry.py +127 -0
  12. hypertrader-0.2.1/tests/test_cli_shutdown.py +86 -0
  13. hypertrader-0.2.1/tests/test_session_recovery.py +224 -0
  14. hypertrader-0.2.1/tests/test_trade_journal.py +202 -0
  15. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/helpers.py +18 -6
  16. hypertrader-0.2.1/utils/retry.py +41 -0
  17. hypertrader-0.2.1/utils/session_state.py +51 -0
  18. hypertrader-0.2.1/utils/trade_journal.py +186 -0
  19. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/dependency_links.txt +0 -0
  20. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/entry_points.txt +0 -0
  21. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/requires.txt +0 -0
  22. {hypertrader-0.1.9 → hypertrader-0.2.1}/hypertrader.egg-info/top_level.txt +0 -0
  23. {hypertrader-0.1.9 → hypertrader-0.2.1}/modes/market_maker.py +0 -0
  24. {hypertrader-0.1.9 → hypertrader-0.2.1}/modes/position_watcher.py +0 -0
  25. {hypertrader-0.1.9 → hypertrader-0.2.1}/modes/trailing_stop.py +0 -0
  26. {hypertrader-0.1.9 → hypertrader-0.2.1}/setup.cfg +0 -0
  27. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/__init__.py +0 -0
  28. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/default.py +0 -0
  29. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/orderflow_metrics.py +0 -0
  30. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/orderflow_models.py +0 -0
  31. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/orderflow_pullback.py +0 -0
  32. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/registry.py +0 -0
  33. {hypertrader-0.1.9 → hypertrader-0.2.1}/strategies/reversal.py +0 -0
  34. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_async_hyperliquid.py +0 -0
  35. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_auto_dry_run.py +0 -0
  36. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_auto_strategy_registry.py +0 -0
  37. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_auto_trader_logging.py +0 -0
  38. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_fib_reversal_strategy.py +0 -0
  39. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_market_ids.py +0 -0
  40. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_orderflow_metrics.py +0 -0
  41. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_orderflow_pullback_lifecycle.py +0 -0
  42. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_reversal_strategy.py +0 -0
  43. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_simulated_logging.py +0 -0
  44. {hypertrader-0.1.9 → hypertrader-0.2.1}/tests/test_trailing_stop.py +0 -0
  45. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/constants.py +0 -0
  46. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/simulated_logging.py +0 -0
  47. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/style.py +0 -0
  48. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/timer.py +0 -0
  49. {hypertrader-0.1.9 → hypertrader-0.2.1}/utils/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypertrader
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Async Hyperliquid trading helper built on the async SDK.
5
5
  Author: darkerego
6
6
  License: MIT
@@ -69,6 +69,7 @@ The canonical bot file in this repo is [`hypertrader.py`](/media/anon/developmen
69
69
  Install from pip: https://pypi.org/project/hypertrader
70
70
 
71
71
  <pre>
72
+ pip install --upgrade pip setuptools wheel
72
73
  pip install hypertrader[auto] --upgrade
73
74
  </pre>
74
75
 
@@ -323,6 +324,7 @@ Key options:
323
324
  - `--scalp`
324
325
  - `--use-live-candle`
325
326
  - `--take-profit-pct`: override Bollinger-derived TP
327
+ - `--take-profit-scale`: multiply target distances from entry (default `1.0`; `0.5` halves them)
326
328
  - `--min-take-profit-pct`
327
329
  - `--max-take-profit-pct`
328
330
  - `--stop-loss-pct`
@@ -363,6 +365,8 @@ Key options:
363
365
 
364
366
  `auto` derives TP from Bollinger Bands unless `--take-profit-pct` overrides it. If TP is set and SL is omitted, SL defaults to half TP. Executions route through the same bracket-entry path used by `enter`.
365
367
 
368
+ `--take-profit-scale 0.5` moves each planned target halfway toward entry, for both longs and shorts: `new_target = entry + 0.5 * (target - entry)`. For example, an entry of 100 with targets 110, 120, and 130 becomes 105, 110, and 115. Scaling applies after strategy signal selection and before exchange price rounding, including Fibonacci targets and dry runs. Stops and allocation percentages stay the same. The multiplier must be finite and positive; `1.0` preserves the original distances.
369
+
366
370
  Fibonacci pullback strategy:
367
371
 
368
372
  ```bash
@@ -566,6 +570,24 @@ The websocket cache is used as the fast path for market data such as mids, best
566
570
 
567
571
  ## Logging
568
572
 
573
+ Each new `auto` session (live or dry-run) creates a unique folder under `logs/sessions/` and prints its location. Restarting an unfinished session with the same account and trading settings automatically resumes that folder and appends to its journal. Use `--session-log-dir PATH` to choose another parent directory. Each folder contains:
574
+
575
+ - `session.json`: the original CLI arguments, parsed CLI settings including defaults, and the arguments passed to the auto trader. Environment variables and exchange clients are not serialized.
576
+ - `closed_trades.csv`: one row per completed position cycle, with UTC start/close times, direction, strategy, requested and filled sizes, size-weighted entry/exit prices, PnL, fees, and links to trade details. Rows are saved as trades complete; cancelled or failed tasks are not counted as closed trades.
577
+ - A JSON file per trade with the signal snapshot and raw exchange fills. Missing fill/PnL data produces blank CSV values with an explanation in `pnl_status`. Live PnL subtracts fill fees but excludes funding; simulated PnL excludes fees, funding, and slippage. Start/close times describe the managed cycle, including entry attempts and closure detection.
578
+
579
+ Atomic `.active-*.json` checkpoints in the parent directory retain session PnL and peaks, completed-trade counts, per-coin streaks and cooldown deadlines, pending trades, and Fibonacci impulses already traded. Live monitors restore saved hidden targets, order IDs, and trailing-stop state; interrupted entry attempts reconcile the existing position without submitting a new entry. Simulations restore entry price, remaining size, partial profits, and the next target. Completed results awaiting accounting are replayed without duplicating CSV rows.
580
+
581
+ Keep the same session directory and trading settings when restarting after an error. Accounts, networks, strategies, settings, and live/dry-run modes have separate checkpoints; simultaneous processes cannot share one checkpoint. `--new-session` deliberately resets recovery state and starts a new journal. A session that exits normally after its configured trade or risk limit is complete, so the next invocation starts a new one. Recovery begins with sessions created by this version; older logs alone cannot restore open-trade state. Local stops and simulated fills only run while the bot is running, and resume from the last saved state using current market prices.
582
+
583
+ Add `--trade-charts` to save an SVG price chart for each completed trade:
584
+
585
+ ```bash
586
+ python3 hypertrader.py auto SOL --size 10 --dry-run --trade-charts
587
+ ```
588
+
589
+ Charts plot candle prices across the trade with size-weighted entry/exit markers. The candle interval adapts to the trade duration, and the latest candle may be incomplete. Charts require no extra plotting packages. The CSV is written before chart generation; the per-trade JSON records chart success, failure, or interruption. `chart_file` is the intended relative path and may not exist if chart generation fails. Charting is off by default and adds no candle requests when disabled.
590
+
569
591
  Dry-run console output, runtime messages, risk events, and simulated trades are written to `logs/simulated.log`. Simulation fills at observed market mid prices. Plans with explicit take-profit allocations, including `fib_reversal`, close the allocated portion of the original size at each reached target (40% at TP1, 35% at TP2, and 25% at TP3 for Fibonacci). Each fill logs a `simulated_take_profit_filled` event with its size and PnL. Position records track remaining size, cumulative realized PnL, and unrealized PnL on the remaining position; a stop closes only that remainder. Completed-trade PnL includes all partial exits. Plans without explicit allocations exit the full position at the stop or final target. Fees, funding, slippage, and dynamic stop adjustments are not modeled. Open positions at shutdown are logged with realized partial profits and their remaining unrealized PnL.
570
592
 
571
593
  Runtime logs for live runs are written to [`logs/hypertrader.log`](/media/anon/development/anon/PycharmProjects/hypertrader/logs/hypertrader.log).
@@ -38,6 +38,7 @@ The canonical bot file in this repo is [`hypertrader.py`](/media/anon/developmen
38
38
  Install from pip: https://pypi.org/project/hypertrader
39
39
 
40
40
  <pre>
41
+ pip install --upgrade pip setuptools wheel
41
42
  pip install hypertrader[auto] --upgrade
42
43
  </pre>
43
44
 
@@ -292,6 +293,7 @@ Key options:
292
293
  - `--scalp`
293
294
  - `--use-live-candle`
294
295
  - `--take-profit-pct`: override Bollinger-derived TP
296
+ - `--take-profit-scale`: multiply target distances from entry (default `1.0`; `0.5` halves them)
295
297
  - `--min-take-profit-pct`
296
298
  - `--max-take-profit-pct`
297
299
  - `--stop-loss-pct`
@@ -332,6 +334,8 @@ Key options:
332
334
 
333
335
  `auto` derives TP from Bollinger Bands unless `--take-profit-pct` overrides it. If TP is set and SL is omitted, SL defaults to half TP. Executions route through the same bracket-entry path used by `enter`.
334
336
 
337
+ `--take-profit-scale 0.5` moves each planned target halfway toward entry, for both longs and shorts: `new_target = entry + 0.5 * (target - entry)`. For example, an entry of 100 with targets 110, 120, and 130 becomes 105, 110, and 115. Scaling applies after strategy signal selection and before exchange price rounding, including Fibonacci targets and dry runs. Stops and allocation percentages stay the same. The multiplier must be finite and positive; `1.0` preserves the original distances.
338
+
335
339
  Fibonacci pullback strategy:
336
340
 
337
341
  ```bash
@@ -535,6 +539,24 @@ The websocket cache is used as the fast path for market data such as mids, best
535
539
 
536
540
  ## Logging
537
541
 
542
+ Each new `auto` session (live or dry-run) creates a unique folder under `logs/sessions/` and prints its location. Restarting an unfinished session with the same account and trading settings automatically resumes that folder and appends to its journal. Use `--session-log-dir PATH` to choose another parent directory. Each folder contains:
543
+
544
+ - `session.json`: the original CLI arguments, parsed CLI settings including defaults, and the arguments passed to the auto trader. Environment variables and exchange clients are not serialized.
545
+ - `closed_trades.csv`: one row per completed position cycle, with UTC start/close times, direction, strategy, requested and filled sizes, size-weighted entry/exit prices, PnL, fees, and links to trade details. Rows are saved as trades complete; cancelled or failed tasks are not counted as closed trades.
546
+ - A JSON file per trade with the signal snapshot and raw exchange fills. Missing fill/PnL data produces blank CSV values with an explanation in `pnl_status`. Live PnL subtracts fill fees but excludes funding; simulated PnL excludes fees, funding, and slippage. Start/close times describe the managed cycle, including entry attempts and closure detection.
547
+
548
+ Atomic `.active-*.json` checkpoints in the parent directory retain session PnL and peaks, completed-trade counts, per-coin streaks and cooldown deadlines, pending trades, and Fibonacci impulses already traded. Live monitors restore saved hidden targets, order IDs, and trailing-stop state; interrupted entry attempts reconcile the existing position without submitting a new entry. Simulations restore entry price, remaining size, partial profits, and the next target. Completed results awaiting accounting are replayed without duplicating CSV rows.
549
+
550
+ Keep the same session directory and trading settings when restarting after an error. Accounts, networks, strategies, settings, and live/dry-run modes have separate checkpoints; simultaneous processes cannot share one checkpoint. `--new-session` deliberately resets recovery state and starts a new journal. A session that exits normally after its configured trade or risk limit is complete, so the next invocation starts a new one. Recovery begins with sessions created by this version; older logs alone cannot restore open-trade state. Local stops and simulated fills only run while the bot is running, and resume from the last saved state using current market prices.
551
+
552
+ Add `--trade-charts` to save an SVG price chart for each completed trade:
553
+
554
+ ```bash
555
+ python3 hypertrader.py auto SOL --size 10 --dry-run --trade-charts
556
+ ```
557
+
558
+ Charts plot candle prices across the trade with size-weighted entry/exit markers. The candle interval adapts to the trade duration, and the latest candle may be incomplete. Charts require no extra plotting packages. The CSV is written before chart generation; the per-trade JSON records chart success, failure, or interruption. `chart_file` is the intended relative path and may not exist if chart generation fails. Charting is off by default and adds no candle requests when disabled.
559
+
538
560
  Dry-run console output, runtime messages, risk events, and simulated trades are written to `logs/simulated.log`. Simulation fills at observed market mid prices. Plans with explicit take-profit allocations, including `fib_reversal`, close the allocated portion of the original size at each reached target (40% at TP1, 35% at TP2, and 25% at TP3 for Fibonacci). Each fill logs a `simulated_take_profit_filled` event with its size and PnL. Position records track remaining size, cumulative realized PnL, and unrealized PnL on the remaining position; a stop closes only that remainder. Completed-trade PnL includes all partial exits. Plans without explicit allocations exit the full position at the stop or final target. Fees, funding, slippage, and dynamic stop adjustments are not modeled. Open positions at shutdown are logged with realized partial profits and their remaining unrealized PnL.
539
561
 
540
562
  Runtime logs for live runs are written to [`logs/hypertrader.log`](/media/anon/development/anon/PycharmProjects/hypertrader/logs/hypertrader.log).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypertrader
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Async Hyperliquid trading helper built on the async SDK.
5
5
  Author: darkerego
6
6
  License: MIT
@@ -69,6 +69,7 @@ The canonical bot file in this repo is [`hypertrader.py`](/media/anon/developmen
69
69
  Install from pip: https://pypi.org/project/hypertrader
70
70
 
71
71
  <pre>
72
+ pip install --upgrade pip setuptools wheel
72
73
  pip install hypertrader[auto] --upgrade
73
74
  </pre>
74
75
 
@@ -323,6 +324,7 @@ Key options:
323
324
  - `--scalp`
324
325
  - `--use-live-candle`
325
326
  - `--take-profit-pct`: override Bollinger-derived TP
327
+ - `--take-profit-scale`: multiply target distances from entry (default `1.0`; `0.5` halves them)
326
328
  - `--min-take-profit-pct`
327
329
  - `--max-take-profit-pct`
328
330
  - `--stop-loss-pct`
@@ -363,6 +365,8 @@ Key options:
363
365
 
364
366
  `auto` derives TP from Bollinger Bands unless `--take-profit-pct` overrides it. If TP is set and SL is omitted, SL defaults to half TP. Executions route through the same bracket-entry path used by `enter`.
365
367
 
368
+ `--take-profit-scale 0.5` moves each planned target halfway toward entry, for both longs and shorts: `new_target = entry + 0.5 * (target - entry)`. For example, an entry of 100 with targets 110, 120, and 130 becomes 105, 110, and 115. Scaling applies after strategy signal selection and before exchange price rounding, including Fibonacci targets and dry runs. Stops and allocation percentages stay the same. The multiplier must be finite and positive; `1.0` preserves the original distances.
369
+
366
370
  Fibonacci pullback strategy:
367
371
 
368
372
  ```bash
@@ -566,6 +570,24 @@ The websocket cache is used as the fast path for market data such as mids, best
566
570
 
567
571
  ## Logging
568
572
 
573
+ Each new `auto` session (live or dry-run) creates a unique folder under `logs/sessions/` and prints its location. Restarting an unfinished session with the same account and trading settings automatically resumes that folder and appends to its journal. Use `--session-log-dir PATH` to choose another parent directory. Each folder contains:
574
+
575
+ - `session.json`: the original CLI arguments, parsed CLI settings including defaults, and the arguments passed to the auto trader. Environment variables and exchange clients are not serialized.
576
+ - `closed_trades.csv`: one row per completed position cycle, with UTC start/close times, direction, strategy, requested and filled sizes, size-weighted entry/exit prices, PnL, fees, and links to trade details. Rows are saved as trades complete; cancelled or failed tasks are not counted as closed trades.
577
+ - A JSON file per trade with the signal snapshot and raw exchange fills. Missing fill/PnL data produces blank CSV values with an explanation in `pnl_status`. Live PnL subtracts fill fees but excludes funding; simulated PnL excludes fees, funding, and slippage. Start/close times describe the managed cycle, including entry attempts and closure detection.
578
+
579
+ Atomic `.active-*.json` checkpoints in the parent directory retain session PnL and peaks, completed-trade counts, per-coin streaks and cooldown deadlines, pending trades, and Fibonacci impulses already traded. Live monitors restore saved hidden targets, order IDs, and trailing-stop state; interrupted entry attempts reconcile the existing position without submitting a new entry. Simulations restore entry price, remaining size, partial profits, and the next target. Completed results awaiting accounting are replayed without duplicating CSV rows.
580
+
581
+ Keep the same session directory and trading settings when restarting after an error. Accounts, networks, strategies, settings, and live/dry-run modes have separate checkpoints; simultaneous processes cannot share one checkpoint. `--new-session` deliberately resets recovery state and starts a new journal. A session that exits normally after its configured trade or risk limit is complete, so the next invocation starts a new one. Recovery begins with sessions created by this version; older logs alone cannot restore open-trade state. Local stops and simulated fills only run while the bot is running, and resume from the last saved state using current market prices.
582
+
583
+ Add `--trade-charts` to save an SVG price chart for each completed trade:
584
+
585
+ ```bash
586
+ python3 hypertrader.py auto SOL --size 10 --dry-run --trade-charts
587
+ ```
588
+
589
+ Charts plot candle prices across the trade with size-weighted entry/exit markers. The candle interval adapts to the trade duration, and the latest candle may be incomplete. Charts require no extra plotting packages. The CSV is written before chart generation; the per-trade JSON records chart success, failure, or interruption. `chart_file` is the intended relative path and may not exist if chart generation fails. Charting is off by default and adds no candle requests when disabled.
590
+
569
591
  Dry-run console output, runtime messages, risk events, and simulated trades are written to `logs/simulated.log`. Simulation fills at observed market mid prices. Plans with explicit take-profit allocations, including `fib_reversal`, close the allocated portion of the original size at each reached target (40% at TP1, 35% at TP2, and 25% at TP3 for Fibonacci). Each fill logs a `simulated_take_profit_filled` event with its size and PnL. Position records track remaining size, cumulative realized PnL, and unrealized PnL on the remaining position; a stop closes only that remainder. Completed-trade PnL includes all partial exits. Plans without explicit allocations exit the full position at the stop or final target. Fees, funding, slippage, and dynamic stop adjustments are not modeled. Open positions at shutdown are logged with realized partial profits and their remaining unrealized PnL.
570
592
 
571
593
  Runtime logs for live runs are written to [`logs/hypertrader.log`](/media/anon/development/anon/PycharmProjects/hypertrader/logs/hypertrader.log).
@@ -21,20 +21,27 @@ strategies/orderflow_models.py
21
21
  strategies/orderflow_pullback.py
22
22
  strategies/registry.py
23
23
  strategies/reversal.py
24
+ tests/test_api_retry.py
24
25
  tests/test_async_hyperliquid.py
25
26
  tests/test_auto_dry_run.py
26
27
  tests/test_auto_strategy_registry.py
27
28
  tests/test_auto_trader_logging.py
29
+ tests/test_cli_shutdown.py
28
30
  tests/test_fib_reversal_strategy.py
29
31
  tests/test_market_ids.py
30
32
  tests/test_orderflow_metrics.py
31
33
  tests/test_orderflow_pullback_lifecycle.py
32
34
  tests/test_reversal_strategy.py
35
+ tests/test_session_recovery.py
33
36
  tests/test_simulated_logging.py
37
+ tests/test_trade_journal.py
34
38
  tests/test_trailing_stop.py
35
39
  utils/constants.py
36
40
  utils/helpers.py
41
+ utils/retry.py
42
+ utils/session_state.py
37
43
  utils/simulated_logging.py
38
44
  utils/style.py
39
45
  utils/timer.py
46
+ utils/trade_journal.py
40
47
  utils/worker.py
@@ -300,6 +300,8 @@ def build_arg_parser() -> argparse.ArgumentParser:
300
300
  help="Use the latest candle even if it may still be forming. Default uses last closed candle.")
301
301
  auto_parser.add_argument("--take-profit-pct", type=float, default=None,
302
302
  help="Override Bollinger-derived TP fraction, e.g. 0.01 = 1pct.")
303
+ auto_parser.add_argument("--take-profit-scale", type=float, default=1.0,
304
+ help="Multiply each target's distance from entry; 0.5 halves it. Default: 1.")
303
305
  auto_parser.add_argument("--min-take-profit-pct", type=float, default=0.002,
304
306
  help="Minimum Bollinger-derived TP fraction. Default: 0.002.")
305
307
  auto_parser.add_argument("--max-take-profit-pct", type=float, default=0.03,
@@ -337,6 +339,12 @@ def build_arg_parser() -> argparse.ArgumentParser:
337
339
  auto_parser.add_argument("--keep-existing-tpsl", action="store_true",
338
340
  help="Do not cancel existing reduce-only TP/SL orders before entry.")
339
341
  auto_parser.add_argument("--dry-run", action="store_true", help="Simulate positions using 10,000 cUSDC assumed collateral and log to logs/simulated.log.")
342
+ auto_parser.add_argument("--session-log-dir", default="logs/sessions",
343
+ help="Parent directory for per-run settings and closed-trade CSV files. Default: logs/sessions.")
344
+ auto_parser.add_argument("--new-session", action="store_true",
345
+ help="Start fresh instead of resuming the matching unfinished auto session.")
346
+ auto_parser.add_argument("--trade-charts", action="store_true",
347
+ help="Save an SVG price chart when each auto position closes.")
340
348
  auto_parser.add_argument("--max-trades", type=int, default=0,
341
349
  help="Maximum completed auto trades before exit. 0 means unlimited. Default: 0.")
342
350
  auto_parser.add_argument("--cooldown-after-trade", type=float, default=60.0,
@@ -877,6 +885,12 @@ async def async_main(argv: Optional[List[str]] = None) -> None:
877
885
  use_last_closed_candle=(not args.use_live_candle),
878
886
  use_sar_stop_on_shortest_interval=args.auto_sar_stop_on_shortest_interval,
879
887
  dry_run=args.dry_run,
888
+ session_log_dir=args.session_log_dir,
889
+ new_session=args.new_session,
890
+ take_profit_scale=args.take_profit_scale,
891
+ trade_charts=args.trade_charts,
892
+ session_argv=list(sys.argv[1:] if argv is None else argv),
893
+ session_cli_settings=vars(args).copy(),
880
894
  max_trades=args.max_trades,
881
895
  cooldown_after_trade=args.cooldown_after_trade,
882
896
  loop_after_trade=args.loop_after_trade,
@@ -1033,45 +1047,40 @@ async def async_main(argv: Optional[List[str]] = None) -> None:
1033
1047
 
1034
1048
  def main(argv: Optional[List[str]] = None) -> None:
1035
1049
  from utils.simulated_logging import LoggedConsole
1036
- def start():
1037
- _loop = asyncio.new_event_loop()
1038
- asyncio.set_event_loop(_loop)
1039
- install_asyncio_exception_logging(_loop)
1050
+
1051
+ async def start() -> None:
1052
+ install_asyncio_exception_logging(asyncio.get_running_loop())
1040
1053
  print(f"[LOG] Writing runtime logs to {log_path}")
1041
1054
  print(f"[START] argv={argv if argv is not None else sys.argv[1:]}")
1042
- _loop.run_until_complete(async_main(argv))
1055
+ await async_main(argv)
1043
1056
 
1044
1057
  args = argv if argv is not None else sys.argv[1:]
1045
1058
  dry_run = "--dry-run" in args
1046
1059
  log_path = configure_runtime_logging(SIMULATED_LOG_FILE if dry_run else None)
1047
1060
  original_stdout, original_stderr = sys.stdout, sys.stderr
1048
- restart = False
1049
1061
  if dry_run:
1050
1062
  sys.stdout = LoggedConsole(original_stdout)
1051
1063
  # sys.stderr = LoggedConsole(original_stderr)
1052
1064
  try:
1053
- start()
1054
- except KeyboardInterrupt:
1055
- print("\n[!] Interrupted.")
1056
- except Exception as err:
1057
- logging.getLogger("hypertrader").exception("[FATAL] Unhandled main() exception: %s" % err)
1058
- restart = True
1059
-
1060
-
1065
+ # Give both the initial run and the single retry a complete lifecycle:
1066
+ # cancellation, awaited cleanup, then event-loop shutdown.
1067
+ for attempt in range(2):
1068
+ try:
1069
+ asyncio.run(start())
1070
+ break
1071
+ except KeyboardInterrupt:
1072
+ print("\n[!] Interrupted.")
1073
+ break
1074
+ except Exception as err:
1075
+ logging.getLogger("hypertrader").exception("[FATAL] Unhandled main() exception: %s", err)
1076
+ if attempt == 1:
1077
+ raise
1078
+ print('[!] Restarting ... ')
1061
1079
  finally:
1062
1080
  if dry_run:
1063
1081
  sys.stdout.flush()
1064
1082
  sys.stderr.flush()
1065
1083
  sys.stdout, sys.stderr = original_stdout, original_stderr
1066
- try:
1067
- loop = asyncio.get_event_loop()
1068
- except RuntimeError:
1069
- loop = None
1070
- if loop is not None and not loop.is_closed():
1071
- loop.close()
1072
- if restart:
1073
- print('[!] Restarting ... ')
1074
- start()
1075
1084
 
1076
1085
 
1077
1086
  if __name__ == "__main__":