Run multiple live configurations in parallel #3

Closed
opened 2026-06-21 14:02:18 +02:00 by pregno · 15 comments
Owner

Run Multiple Live Configurations in Parallel Implementation Plan

Goal: add a live-many command that runs multiple paper/live config files concurrently in one process, with per-entry cash caps, isolated runtime artifacts, shared trading-client pooling, graceful shutdown, and a simple operational dashboard.

Global constraints:

  • Do not implement parallel backtests or sweeps.
  • Do not add shared account-level allocation or total exposure tracking.
  • cash_cap means maximum notional value per entry order.
  • cash_cap is required for mode: paper and mode: live; it is not required for mode: backtest.
  • live-many must always namespace journal_path, error_log_path, and halt_file filenames by bot label while preserving directories.
  • Labels come from config paths relative to the current working directory, with extensions removed and non-alphanumeric/path separators normalized to -.
  • live-many requires at least two --config values.
  • Mixed paper and live configs are allowed; existing I_UNDERSTAND_LIVE_TRADING=yes guard remains for real live configs.
  • Ctrl-C must stop bot threads gracefully without writing halt files or closing positions.
  • Use TDD: write or update tests before each implementation change, then run the targeted tests.

Task 1: Add cash_cap config validation

Files:

  • Modify: pivotbot/config.py
  • Modify: config.example.yaml
  • Modify: config.btc.yaml
  • Test: tests/test_config.py

Steps:

  • Add tests in tests/test_config.py proving cash_cap loads for paper configs, is required for paper/live configs, is not required for backtest configs, and rejects non-positive values.
  • Run python -m pytest tests/test_config.py -v and confirm the new tests fail before implementation.
  • Add cash_cap: float | None = None to Config in pivotbot/config.py.
  • In load_config(), after cfg = Config(**raw) and existing enum validation, raise ValueError("cash_cap is required when mode is paper or live") when cfg.mode in {"paper", "live"} and cfg.cash_cap is None.
  • In load_config(), raise a clear ValueError("cash_cap must be positive") when cfg.cash_cap is not None and cfg.cash_cap <= 0.
  • Preserve existing live guard behavior for mode: live and I_UNDERSTAND_LIVE_TRADING=yes.
  • Add cash_cap: 10000 plus a comment to config.example.yaml and config.btc.yaml explaining it is the max notional value per entry order and must be adjusted by the user.
  • Run python -m pytest tests/test_config.py -v and confirm it passes.

Task 2: Apply cash_cap to live broker order sizing

Files:

  • Modify: pivotbot/broker.py
  • Test: tests/test_alpaca_broker.py

Steps:

  • Add tests in tests/test_alpaca_broker.py for stock order quantity capped by cash_cap / entry_price, crypto quantity capped by cash_cap / entry_price, cash cap composing with buying-power cap by taking the smaller quantity, stock whole-share flooring, and crypto 6-decimal rounding.
  • Run python -m pytest tests/test_alpaca_broker.py -v and confirm the new tests fail before implementation.
  • Add an AlpacaBroker helper such as _cap_to_cash_cap(self, qty: float, ref_price: float) -> float that returns qty unchanged when cfg.cash_cap is None or ref_price <= 0, otherwise returns min(qty, cfg.cash_cap / ref_price).
  • In AlpacaBroker.submit_entry(), apply both _cap_to_buying_power() and _cap_to_cash_cap() before stock flooring or crypto rounding.
  • Ensure the final quantity is never increased by either cap and existing zero/too-small order behavior remains unchanged.
  • Run python -m pytest tests/test_alpaca_broker.py -v and confirm it passes.

Task 3: Extract reusable live-runner construction

Files:

  • Modify: pivotbot/__main__.py
  • Test: existing CLI/live tests as smoke coverage

Steps:

  • Create a helper in pivotbot/__main__.py, for example build_live_runner(cfg, *, quiet: bool = False, trading_client=None, reporter=None) -> LiveRunner, that contains the current object wiring from cmd_live().
  • The helper must construct AlpacaBroker(cfg, trading_client=trading_client), use AlwaysOpen() for crypto and AlpacaClock(broker.trading_client) for stocks, construct LiveBarFeed(cfg), Journal(cfg.journal_path), and ErrorLog(cfg.error_log_path), and default to QuietReporter() when quiet is true or ConsoleReporter() when false unless an explicit reporter is provided.
  • Update cmd_live() to load config and call the helper, then runner.run().
  • Run python -m pytest tests/test_cli.py tests/test_live_runner.py -v and confirm existing behavior still passes.

Task 4: Add label and artifact namespacing helpers

Files:

  • Create: pivotbot/live_many.py
  • Test: create tests/test_live_many.py

Steps:

  • Add tests in tests/test_live_many.py for label derivation: config.spy.yaml -> config-spy, config.btc.yaml -> config-btc, configs/a/config.yaml -> configs-a-config, and configs/b/config.yaml -> configs-b-config when relative to the current working directory.
  • Add tests for duplicate normalized labels being rejected with a clear error.
  • Add tests for artifact namespacing that preserves directories: pivotbot.db -> pivotbot.<label>.db, logs/pivotbot.db -> logs/pivotbot.<label>.db, errors.log -> errors.<label>.log, and run/HALT -> run/HALT.<label>.
  • Run python -m pytest tests/test_live_many.py -v and confirm the tests fail before implementation.
  • Implement derive_label(config_path: str | Path, cwd: str | Path = Path.cwd()) -> str in pivotbot/live_many.py.
  • Implement ensure_unique_labels(labels: Iterable[str]) -> None that raises ValueError on duplicates.
  • Implement namespace_path(path: str | Path, label: str) -> str that inserts .<label> before a file extension when one exists and appends .<label> when no extension exists.
  • Implement isolate_runtime_paths(cfg: Config, label: str) -> Config using dataclasses.replace() to update journal_path, error_log_path, and halt_file.
  • Run python -m pytest tests/test_live_many.py -v and confirm it passes.

Task 5: Add live-many CLI parsing

Files:

  • Modify: pivotbot/__main__.py
  • Modify: pivotbot/live_many.py
  • Test: tests/test_cli.py

Steps:

  • Add parser tests in tests/test_cli.py proving live-many accepts repeated --config, supports --quiet, and rejects fewer than two configs through parser validation or command-level validation.
  • Run python -m pytest tests/test_cli.py -v and confirm the new tests fail before implementation.
  • Add a live-many subparser in build_parser() with --config using action="append", required=True, and --quiet using action="store_true".
  • Add cmd_live_many(args) in pivotbot/__main__.py that delegates to pivotbot.live_many.run_live_many_command(args.config, quiet=args.quiet).
  • In run_live_many_command(), fail fast with SystemExit("live-many requires at least two --config values") when fewer than two configs are provided.
  • Run python -m pytest tests/test_cli.py -v and confirm it passes.

Task 6: Add trading-client pooling

Files:

  • Modify: pivotbot/live_many.py
  • Test: tests/test_live_many.py

Steps:

  • Add tests for a trading-client pool keyed by (mode, api_key, api_secret): two configs with the same key reuse one client, different modes use different clients, and secrets are not printed or exposed by helper output.
  • Run python -m pytest tests/test_live_many.py -v and confirm the new tests fail before implementation.
  • Implement a small pool helper, for example TradingClientPool, that accepts an optional factory for tests and returns a client for each (mode, api_key, api_secret) key.
  • The default factory should construct alpaca.trading.client.TradingClient(api_key, api_secret, paper=(mode != "live")).
  • Ensure this pool is only for trading clients; do not share data clients or LiveBarFeed instances.
  • Run python -m pytest tests/test_live_many.py -v and confirm it passes.

Task 7: Make live running stop-aware without changing single live behavior

Files:

  • Modify: pivotbot/runner.py
  • Test: tests/test_live_runner.py

Steps:

  • Add tests proving a stop event or stop predicate allows a live loop to exit without touching the halt file and without closing positions.
  • Run python -m pytest tests/test_live_runner.py -v and confirm the new tests fail before implementation.
  • Add a stop-aware method to LiveRunner, for example run_until_stopped(stop_event, sleep_seconds: int = 60), that calls reporter.startup(), logs the same start event as run(), repeatedly calls _run_once(datetime.now(timezone.utc)), and waits using stop_event.wait(sleep_seconds) so shutdown is interruptible.
  • Update existing run() to preserve current behavior, either by keeping its existing infinite loop or by delegating to the new method with an event that is never set.
  • Ensure stop-aware shutdown does not create cfg.halt_file and does not call broker.close_all().
  • Run python -m pytest tests/test_live_runner.py -v and confirm it passes.

Task 8: Implement dashboard state and reporter adapter

Files:

  • Modify: pivotbot/live_many.py
  • Test: tests/test_live_many.py

Steps:

  • Add tests for dashboard state updates on startup, day header, bar pulse, market closed, status changes, consecutive error updates, quiet mode suppressing rendering, and heartbeat rendering eligibility.
  • Run python -m pytest tests/test_live_many.py -v and confirm the new tests fail before implementation.
  • Implement a BotStatus dataclass with fields: label, symbol, mode, status, last_pulse, consecutive_errors, and last_update.
  • Implement a thread-safe dashboard model that stores one BotStatus per label and marks itself dirty on state changes.
  • Implement a reporter adapter with the same methods used by LiveRunner reporters: startup(cfg), day_header(day, symbol, levels), bar(char), and market_closed(); the adapter updates the dashboard instead of writing raw pulse output.
  • Implement rendering that uses a refreshed block when the output stream is a TTY and periodic snapshots when it is not a TTY.
  • Implement quiet=True behavior that updates state but suppresses dashboard rendering.
  • Run python -m pytest tests/test_live_many.py -v and confirm it passes.

Task 9: Implement threaded live-many supervisor

Files:

  • Modify: pivotbot/live_many.py
  • Modify: pivotbot/__main__.py if helper signatures need adjustment
  • Test: tests/test_live_many.py

Steps:

  • Add tests for loading multiple configs, deriving labels, rejecting duplicate labels, isolating runtime paths, constructing one runner per config, passing pooled trading clients into runner construction, keeping data feeds independent, marking failed bot threads as failed, and stopping all threads through a stop event.
  • Run python -m pytest tests/test_live_many.py -v and confirm the new tests fail before implementation.
  • Implement run_live_many_command(config_paths: list[str], *, quiet: bool = False) -> None to validate count, load configs, derive unique labels, isolate runtime paths, create the dashboard, create the trading-client pool, build one runner per config, and start one thread per runner.
  • Each bot thread should call the stop-aware runner loop and update dashboard status to running, stopping, stopped, or failed as appropriate.
  • The supervisor should catch KeyboardInterrupt, set the shared stop event, wait briefly for threads to exit, render a final status if not quiet, and return without writing halt files.
  • Unexpected bot-thread exceptions should mark only that bot as failed and keep other bots supervised.
  • Run python -m pytest tests/test_live_many.py -v and confirm it passes.

Task 10: Documentation and integration verification

Files:

  • Modify: README.md
  • Possibly modify: docker-compose.yml only if documentation requires an example command; do not change default compose behavior unless necessary.
  • Test: full test suite

Steps:

  • Update README.md with a short live-many section showing repeated --config, explaining cash_cap, namespaced artifacts, dashboard behavior, --quiet, and graceful Ctrl-C shutdown.
  • Mention that live-many is for paper/live configs only, not backtest/sweep parallelization.
  • Run python -m pytest -v and confirm the full test suite passes.
  • Run python -m pivotbot live-many --help and confirm the command documents repeated --config and --quiet.
  • Run git status --short and confirm only intended files changed.

Final acceptance checklist

  • python -m pivotbot live-many --config config.spy.yaml --config config.btc.yaml starts two bot workers when both configs are valid.
  • live-many rejects one or zero config paths.
  • cash_cap is mandatory for paper and live, optional for backtest.
  • Each entry order is capped by cash_cap / entry_price before final submission.
  • Runtime artifacts are namespaced by label and preserve configured directories.
  • Trading clients are shared only for identical (mode, api_key, api_secret) keys.
  • Data feeds remain independent per bot.
  • Dashboard shows label, symbol, mode, status, last pulse char, consecutive errors, and last update time.
  • --quiet suppresses dashboard refresh.
  • Ctrl-C stops bot threads without writing halt files and without closing positions.
  • Full test suite passes with python -m pytest -v.
# Run Multiple Live Configurations in Parallel Implementation Plan Goal: add a `live-many` command that runs multiple paper/live config files concurrently in one process, with per-entry cash caps, isolated runtime artifacts, shared trading-client pooling, graceful shutdown, and a simple operational dashboard. Global constraints: - Do not implement parallel backtests or sweeps. - Do not add shared account-level allocation or total exposure tracking. - `cash_cap` means maximum notional value per entry order. - `cash_cap` is required for `mode: paper` and `mode: live`; it is not required for `mode: backtest`. - `live-many` must always namespace `journal_path`, `error_log_path`, and `halt_file` filenames by bot label while preserving directories. - Labels come from config paths relative to the current working directory, with extensions removed and non-alphanumeric/path separators normalized to `-`. - `live-many` requires at least two `--config` values. - Mixed `paper` and `live` configs are allowed; existing `I_UNDERSTAND_LIVE_TRADING=yes` guard remains for real live configs. - Ctrl-C must stop bot threads gracefully without writing halt files or closing positions. - Use TDD: write or update tests before each implementation change, then run the targeted tests. ## Task 1: Add `cash_cap` config validation Files: - Modify: `pivotbot/config.py` - Modify: `config.example.yaml` - Modify: `config.btc.yaml` - Test: `tests/test_config.py` Steps: - [ ] Add tests in `tests/test_config.py` proving `cash_cap` loads for paper configs, is required for paper/live configs, is not required for backtest configs, and rejects non-positive values. - [ ] Run `python -m pytest tests/test_config.py -v` and confirm the new tests fail before implementation. - [ ] Add `cash_cap: float | None = None` to `Config` in `pivotbot/config.py`. - [ ] In `load_config()`, after `cfg = Config(**raw)` and existing enum validation, raise `ValueError("cash_cap is required when mode is paper or live")` when `cfg.mode in {"paper", "live"}` and `cfg.cash_cap is None`. - [ ] In `load_config()`, raise a clear `ValueError("cash_cap must be positive")` when `cfg.cash_cap is not None and cfg.cash_cap <= 0`. - [ ] Preserve existing live guard behavior for `mode: live` and `I_UNDERSTAND_LIVE_TRADING=yes`. - [ ] Add `cash_cap: 10000` plus a comment to `config.example.yaml` and `config.btc.yaml` explaining it is the max notional value per entry order and must be adjusted by the user. - [ ] Run `python -m pytest tests/test_config.py -v` and confirm it passes. ## Task 2: Apply `cash_cap` to live broker order sizing Files: - Modify: `pivotbot/broker.py` - Test: `tests/test_alpaca_broker.py` Steps: - [ ] Add tests in `tests/test_alpaca_broker.py` for stock order quantity capped by `cash_cap / entry_price`, crypto quantity capped by `cash_cap / entry_price`, cash cap composing with buying-power cap by taking the smaller quantity, stock whole-share flooring, and crypto 6-decimal rounding. - [ ] Run `python -m pytest tests/test_alpaca_broker.py -v` and confirm the new tests fail before implementation. - [ ] Add an `AlpacaBroker` helper such as `_cap_to_cash_cap(self, qty: float, ref_price: float) -> float` that returns `qty` unchanged when `cfg.cash_cap is None` or `ref_price <= 0`, otherwise returns `min(qty, cfg.cash_cap / ref_price)`. - [ ] In `AlpacaBroker.submit_entry()`, apply both `_cap_to_buying_power()` and `_cap_to_cash_cap()` before stock flooring or crypto rounding. - [ ] Ensure the final quantity is never increased by either cap and existing zero/too-small order behavior remains unchanged. - [ ] Run `python -m pytest tests/test_alpaca_broker.py -v` and confirm it passes. ## Task 3: Extract reusable live-runner construction Files: - Modify: `pivotbot/__main__.py` - Test: existing CLI/live tests as smoke coverage Steps: - [ ] Create a helper in `pivotbot/__main__.py`, for example `build_live_runner(cfg, *, quiet: bool = False, trading_client=None, reporter=None) -> LiveRunner`, that contains the current object wiring from `cmd_live()`. - [ ] The helper must construct `AlpacaBroker(cfg, trading_client=trading_client)`, use `AlwaysOpen()` for crypto and `AlpacaClock(broker.trading_client)` for stocks, construct `LiveBarFeed(cfg)`, `Journal(cfg.journal_path)`, and `ErrorLog(cfg.error_log_path)`, and default to `QuietReporter()` when `quiet` is true or `ConsoleReporter()` when false unless an explicit reporter is provided. - [ ] Update `cmd_live()` to load config and call the helper, then `runner.run()`. - [ ] Run `python -m pytest tests/test_cli.py tests/test_live_runner.py -v` and confirm existing behavior still passes. ## Task 4: Add label and artifact namespacing helpers Files: - Create: `pivotbot/live_many.py` - Test: create `tests/test_live_many.py` Steps: - [ ] Add tests in `tests/test_live_many.py` for label derivation: `config.spy.yaml -> config-spy`, `config.btc.yaml -> config-btc`, `configs/a/config.yaml -> configs-a-config`, and `configs/b/config.yaml -> configs-b-config` when relative to the current working directory. - [ ] Add tests for duplicate normalized labels being rejected with a clear error. - [ ] Add tests for artifact namespacing that preserves directories: `pivotbot.db -> pivotbot.<label>.db`, `logs/pivotbot.db -> logs/pivotbot.<label>.db`, `errors.log -> errors.<label>.log`, and `run/HALT -> run/HALT.<label>`. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm the tests fail before implementation. - [ ] Implement `derive_label(config_path: str | Path, cwd: str | Path = Path.cwd()) -> str` in `pivotbot/live_many.py`. - [ ] Implement `ensure_unique_labels(labels: Iterable[str]) -> None` that raises `ValueError` on duplicates. - [ ] Implement `namespace_path(path: str | Path, label: str) -> str` that inserts `.<label>` before a file extension when one exists and appends `.<label>` when no extension exists. - [ ] Implement `isolate_runtime_paths(cfg: Config, label: str) -> Config` using `dataclasses.replace()` to update `journal_path`, `error_log_path`, and `halt_file`. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm it passes. ## Task 5: Add `live-many` CLI parsing Files: - Modify: `pivotbot/__main__.py` - Modify: `pivotbot/live_many.py` - Test: `tests/test_cli.py` Steps: - [ ] Add parser tests in `tests/test_cli.py` proving `live-many` accepts repeated `--config`, supports `--quiet`, and rejects fewer than two configs through parser validation or command-level validation. - [ ] Run `python -m pytest tests/test_cli.py -v` and confirm the new tests fail before implementation. - [ ] Add a `live-many` subparser in `build_parser()` with `--config` using `action="append"`, `required=True`, and `--quiet` using `action="store_true"`. - [ ] Add `cmd_live_many(args)` in `pivotbot/__main__.py` that delegates to `pivotbot.live_many.run_live_many_command(args.config, quiet=args.quiet)`. - [ ] In `run_live_many_command()`, fail fast with `SystemExit("live-many requires at least two --config values")` when fewer than two configs are provided. - [ ] Run `python -m pytest tests/test_cli.py -v` and confirm it passes. ## Task 6: Add trading-client pooling Files: - Modify: `pivotbot/live_many.py` - Test: `tests/test_live_many.py` Steps: - [ ] Add tests for a trading-client pool keyed by `(mode, api_key, api_secret)`: two configs with the same key reuse one client, different modes use different clients, and secrets are not printed or exposed by helper output. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm the new tests fail before implementation. - [ ] Implement a small pool helper, for example `TradingClientPool`, that accepts an optional factory for tests and returns a client for each `(mode, api_key, api_secret)` key. - [ ] The default factory should construct `alpaca.trading.client.TradingClient(api_key, api_secret, paper=(mode != "live"))`. - [ ] Ensure this pool is only for trading clients; do not share data clients or `LiveBarFeed` instances. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm it passes. ## Task 7: Make live running stop-aware without changing single `live` behavior Files: - Modify: `pivotbot/runner.py` - Test: `tests/test_live_runner.py` Steps: - [ ] Add tests proving a stop event or stop predicate allows a live loop to exit without touching the halt file and without closing positions. - [ ] Run `python -m pytest tests/test_live_runner.py -v` and confirm the new tests fail before implementation. - [ ] Add a stop-aware method to `LiveRunner`, for example `run_until_stopped(stop_event, sleep_seconds: int = 60)`, that calls `reporter.startup()`, logs the same start event as `run()`, repeatedly calls `_run_once(datetime.now(timezone.utc))`, and waits using `stop_event.wait(sleep_seconds)` so shutdown is interruptible. - [ ] Update existing `run()` to preserve current behavior, either by keeping its existing infinite loop or by delegating to the new method with an event that is never set. - [ ] Ensure stop-aware shutdown does not create `cfg.halt_file` and does not call `broker.close_all()`. - [ ] Run `python -m pytest tests/test_live_runner.py -v` and confirm it passes. ## Task 8: Implement dashboard state and reporter adapter Files: - Modify: `pivotbot/live_many.py` - Test: `tests/test_live_many.py` Steps: - [ ] Add tests for dashboard state updates on startup, day header, bar pulse, market closed, status changes, consecutive error updates, quiet mode suppressing rendering, and heartbeat rendering eligibility. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm the new tests fail before implementation. - [ ] Implement a `BotStatus` dataclass with fields: `label`, `symbol`, `mode`, `status`, `last_pulse`, `consecutive_errors`, and `last_update`. - [ ] Implement a thread-safe dashboard model that stores one `BotStatus` per label and marks itself dirty on state changes. - [ ] Implement a reporter adapter with the same methods used by `LiveRunner` reporters: `startup(cfg)`, `day_header(day, symbol, levels)`, `bar(char)`, and `market_closed()`; the adapter updates the dashboard instead of writing raw pulse output. - [ ] Implement rendering that uses a refreshed block when the output stream is a TTY and periodic snapshots when it is not a TTY. - [ ] Implement `quiet=True` behavior that updates state but suppresses dashboard rendering. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm it passes. ## Task 9: Implement threaded `live-many` supervisor Files: - Modify: `pivotbot/live_many.py` - Modify: `pivotbot/__main__.py` if helper signatures need adjustment - Test: `tests/test_live_many.py` Steps: - [ ] Add tests for loading multiple configs, deriving labels, rejecting duplicate labels, isolating runtime paths, constructing one runner per config, passing pooled trading clients into runner construction, keeping data feeds independent, marking failed bot threads as failed, and stopping all threads through a stop event. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm the new tests fail before implementation. - [ ] Implement `run_live_many_command(config_paths: list[str], *, quiet: bool = False) -> None` to validate count, load configs, derive unique labels, isolate runtime paths, create the dashboard, create the trading-client pool, build one runner per config, and start one thread per runner. - [ ] Each bot thread should call the stop-aware runner loop and update dashboard status to `running`, `stopping`, `stopped`, or `failed` as appropriate. - [ ] The supervisor should catch `KeyboardInterrupt`, set the shared stop event, wait briefly for threads to exit, render a final status if not quiet, and return without writing halt files. - [ ] Unexpected bot-thread exceptions should mark only that bot as failed and keep other bots supervised. - [ ] Run `python -m pytest tests/test_live_many.py -v` and confirm it passes. ## Task 10: Documentation and integration verification Files: - Modify: `README.md` - Possibly modify: `docker-compose.yml` only if documentation requires an example command; do not change default compose behavior unless necessary. - Test: full test suite Steps: - [ ] Update `README.md` with a short `live-many` section showing repeated `--config`, explaining `cash_cap`, namespaced artifacts, dashboard behavior, `--quiet`, and graceful Ctrl-C shutdown. - [ ] Mention that `live-many` is for paper/live configs only, not backtest/sweep parallelization. - [ ] Run `python -m pytest -v` and confirm the full test suite passes. - [ ] Run `python -m pivotbot live-many --help` and confirm the command documents repeated `--config` and `--quiet`. - [ ] Run `git status --short` and confirm only intended files changed. ## Final acceptance checklist - [ ] `python -m pivotbot live-many --config config.spy.yaml --config config.btc.yaml` starts two bot workers when both configs are valid. - [ ] `live-many` rejects one or zero config paths. - [ ] `cash_cap` is mandatory for `paper` and `live`, optional for `backtest`. - [ ] Each entry order is capped by `cash_cap / entry_price` before final submission. - [ ] Runtime artifacts are namespaced by label and preserve configured directories. - [ ] Trading clients are shared only for identical `(mode, api_key, api_secret)` keys. - [ ] Data feeds remain independent per bot. - [ ] Dashboard shows label, symbol, mode, status, last pulse char, consecutive errors, and last update time. - [ ] `--quiet` suppresses dashboard refresh. - [ ] Ctrl-C stops bot threads without writing halt files and without closing positions. - [ ] Full test suite passes with `python -m pytest -v`.
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782081175.966779 -->
Author
Owner

pippero: build failed — spawn devcontainer ENOENT. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T22-32-55-780Z.jsonl

pippero: build failed — spawn devcontainer ENOENT. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T22-32-55-780Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782082675.437499 -->
Author
Owner

pippero: build failed — git worktree add failed (255): Preparing worktree (new branch 'pippero/issue-3-run-multiple-live-configurations-in-para')
fatal: a branch named 'pippero/issue-3-run-multiple-live-configurations-in-para' already exists. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T22-57-55-163Z.jsonl

pippero: build failed — git worktree add failed (255): Preparing worktree (new branch 'pippero/issue-3-run-multiple-live-configurations-in-para') fatal: a branch named 'pippero/issue-3-run-multiple-live-configurations-in-para' already exists. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T22-57-55-163Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782083071.301539 -->
Author
Owner

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:04:32.201Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64.
Error: Filename must be devcontainer.json or .devcontainer.json (/Users/pregno/projects/personal/coding-machine/.worktrees/pippero-base-devcontainer.json).
at MG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:3378)
at GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5774)
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206)
at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743)
at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-04-31-026Z.jsonl

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:04:32.201Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64. Error: Filename must be devcontainer.json or .devcontainer.json (/Users/pregno/projects/personal/coding-machine/.worktrees/pippero-base-devcontainer.json). at MG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:3378) at GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5774) at process.processTicksAndRejections (node:internal/process/task_queues:104:5) at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206) at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743) at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-04-31-026Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782083232.967179 -->
Author
Owner

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:07:13.572Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64.
[2026-06-21T23:07:15.910Z] Error fetching image details: No manifest found for mcr.microsoft.com/devcontainers/universal:2.
[2026-06-21T23:07:16.390Z] Retrying (Attempt 0) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
'
[2026-06-21T23:07:17.784Z] Retrying (Attempt 1) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
'
[2026-06-21T23:07:19.187Z] Retrying (Attempt 2) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
'
[2026-06-21T23:07:20.577Z] Retrying (Attempt 3) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
'
[2026-06-21T23:07:21.964Z] Retrying (Attempt 4) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
'
[2026-06-21T23:07:22.966Z] Command failed: docker inspect --type image mcr.microsoft.com/devcontainers/universal:2
[2026-06-21T23:07:22.966Z] []
[2026-06-21T23:07:22.966Z] Error response from daemon: No such image: mcr.microsoft.com/devcontainers/universal:2

[2026-06-21T23:07:22.966Z] Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
Error: Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2
at $V (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1277)
at fG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1021)
at async f9 (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:4649)
at async GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5768)
at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206)
at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743)
at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-07-12-707Z.jsonl

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:07:13.572Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64. [2026-06-21T23:07:15.910Z] Error fetching image details: No manifest found for mcr.microsoft.com/devcontainers/universal:2. [2026-06-21T23:07:16.390Z] Retrying (Attempt 0) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 ' [2026-06-21T23:07:17.784Z] Retrying (Attempt 1) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 ' [2026-06-21T23:07:19.187Z] Retrying (Attempt 2) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 ' [2026-06-21T23:07:20.577Z] Retrying (Attempt 3) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 ' [2026-06-21T23:07:21.964Z] Retrying (Attempt 4) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 ' [2026-06-21T23:07:22.966Z] Command failed: docker inspect --type image mcr.microsoft.com/devcontainers/universal:2 [2026-06-21T23:07:22.966Z] [] [2026-06-21T23:07:22.966Z] Error response from daemon: No such image: mcr.microsoft.com/devcontainers/universal:2 [2026-06-21T23:07:22.966Z] Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 Error: Command failed: docker pull mcr.microsoft.com/devcontainers/universal:2 at $V (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1277) at fG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1021) at async f9 (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:4649) at async GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5768) at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206) at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743) at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-07-12-707Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782083434.687299 -->
Author
Owner

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:10:35.325Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64.
[2026-06-21T23:10:36.018Z] Error fetching image details: No manifest found for mcr.microsoft.com/devcontainers/universal:linux.
[2026-06-21T23:10:36.436Z] Retrying (Attempt 0) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
'
[2026-06-21T23:10:37.846Z] Retrying (Attempt 1) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
'
[2026-06-21T23:10:39.244Z] Retrying (Attempt 2) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
'
[2026-06-21T23:10:40.638Z] Retrying (Attempt 3) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
'
[2026-06-21T23:10:42.043Z] Retrying (Attempt 4) with error
'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
'
[2026-06-21T23:10:43.045Z] Command failed: docker inspect --type image mcr.microsoft.com/devcontainers/universal:linux
[2026-06-21T23:10:43.045Z] []
[2026-06-21T23:10:43.045Z] Error response from daemon: No such image: mcr.microsoft.com/devcontainers/universal:linux

[2026-06-21T23:10:43.045Z] Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
Error: Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux
at $V (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1277)
at fG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1021)
at async f9 (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:4649)
at async GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5768)
at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206)
at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743)
at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-10-34-515Z.jsonl

pippero: build failed — devcontainer up failed (1): [2026-06-21T23:10:35.325Z] @devcontainers/cli 0.87.0. Node.js v26.3.1. darwin 25.5.0 arm64. [2026-06-21T23:10:36.018Z] Error fetching image details: No manifest found for mcr.microsoft.com/devcontainers/universal:linux. [2026-06-21T23:10:36.436Z] Retrying (Attempt 0) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux ' [2026-06-21T23:10:37.846Z] Retrying (Attempt 1) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux ' [2026-06-21T23:10:39.244Z] Retrying (Attempt 2) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux ' [2026-06-21T23:10:40.638Z] Retrying (Attempt 3) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux ' [2026-06-21T23:10:42.043Z] Retrying (Attempt 4) with error 'Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux ' [2026-06-21T23:10:43.045Z] Command failed: docker inspect --type image mcr.microsoft.com/devcontainers/universal:linux [2026-06-21T23:10:43.045Z] [] [2026-06-21T23:10:43.045Z] Error response from daemon: No such image: mcr.microsoft.com/devcontainers/universal:linux [2026-06-21T23:10:43.045Z] Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux Error: Command failed: docker pull mcr.microsoft.com/devcontainers/universal:linux at $V (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1277) at fG (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:467:1021) at async f9 (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:4649) at async GI (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:5768) at async $Z (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:666:206) at async zZ (/Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:665:15743) at async /Users/pregno/.node_modules/lib/node_modules/@devcontainers/cli/dist/spec-node/devContainersSpecCLI.js:485:1917. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-10-34-515Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782083856.594379 -->
Author
Owner

pippero: build failed — no valid .pippero/result.json produced by the build. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-17-36-339Z.jsonl

pippero: build failed — no valid .pippero/result.json produced by the build. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-17-36-339Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782084849.888079 -->
Author
Owner

pippero: build failed — no valid .pippero/result.json produced by the build. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-34-09-724Z.jsonl

pippero: build failed — no valid .pippero/result.json produced by the build. Log: /Users/pregno/projects/personal/coding-machine/.logs/pregno-daytrading/issue-3/2026-06-21T23-34-09-724Z.jsonl
Author
Owner
No description provided.
<!-- pippero:slack-thread=1782085121.568539 -->
pregno 2026-06-22 02:33:21 +02:00
  • closed this issue
  • removed the
    building
    label
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pregno/daytrading#3
No description provided.