Skip to content

bug: ignore non-deployment entries in the project's live directory - #677

Merged
Martin-Molinero merged 4 commits into
QuantConnect:masterfrom
Amadeus-22:bug-676-live-dir-stray-entries
Oct 15, 2026
Merged

Martin-Molinero merged 4 commits into
QuantConnect:masterfrom
Amadeus-22:bug-676-live-dir-stray-entries

Conversation

@Amadeus-22

Copy link
Copy Markdown
Contributor

Closes #676.

  • With Paper Trading (or any brokerage that supports an initial cash balance or holdings), lean live deploy and lean cloud live deploy aborted with time data '.DS_Store' does not match format '%Y-%m-%d_%H-%M-%S' when <project>/live contained an entry that isn't a deployment timestamp, like a Finder .DS_Store or a directory from an earlier --output.
  • _get_last_portfolio now skips the entries whose name doesn't parse, as is_backtest_output_directory in optimize.py already does. Deployment directories are read as before.
  • Added a parametrized test (a .DS_Store file and a custom directory next to a real deployment) that runs lean live deploy. It fails on master and passes with the fix.
  • pytest tests/commands/test_live.py tests/commands/cloud/live passes (1553 passed, 18 skipped, Python 3.12) and python static_analysis.py is clean.

🤖 Generated with Claude Code

Amadeus-22 and others added 2 commits October 14, 2026 10:33
…tory name format

- A deployment made with `--output live/<name>` was skipped by the name
  parser, so a newer local deployment lost to an older cloud one. Fall
  back to the result file's mtime when the name is not a timestamp.
- Converting a parseable but pre-1970 name to UTC raises OSError on
  Windows; catch it instead of aborting the deploy.
- Move the directory name parser to `output_config_manager` and reuse
  it from `optimize.py` and `live_utils.py`, with the format in
  `OUTPUT_DIRECTORY_NAME_FORMAT`.
- Log ignored entries at debug level, and test `_get_last_portfolio`
  directly with a state file so "ignored" and "still read" differ.
@jhonabreul

jhonabreul commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Thanks for the fix. I pushed a follow-up commit (d2c9a37) on top of it.

Cases that still failed with the previous commit

<project>/live entry Result
my-run, from --output live/my-run Skipped, so an older cloud deployment won and its portfolio was offered
1960-01-01_00-00-00 Parses, but .astimezone() ran outside the try and raises OSError on Windows

The test could not catch these: its deployment directory was empty, so _get_last_portfolio returned None whether or not it was read.

What changed

  • Timestamp names convert to UTC inside the try. Any other directory with an L-*.json is a deployment dated by that file's mtime.
  • The name parser moved to output_config_manager.get_output_directory_timestamp, shared by optimize.py and live_utils.py. The format is now OUTPUT_DIRECTORY_NAME_FORMAT.
  • Ignored entries are logged with --verbose.
  • tests/components/util/test_live_utils.py tests _get_last_portfolio directly with a state file. The command test seeds one too and asserts the cash balance is offered.
  • The custom-directory and pre-1970 cases fail on the previous commit. The live, optimize and backtest suites pass (1709 passed, 18 skipped) and static_analysis.py is clean.

The elif branch still picks the state file by mtime from the working directory, which can differ from the directory that won the comparison. That predates this PR.

On Linux and macOS the name converts to UTC and is just an older
deployment, so nothing is logged for it. Assert only that the newer
deployment's state is still returned.
@jhonabreul

Copy link
Copy Markdown
Collaborator

Pushed 96ae80c to fix CI: the 1960-01-01_00-00-00 case only fails to convert on Windows, so on Linux and macOS it is an older deployment and nothing is logged for it. The test now only asserts that the newer deployment's state is still returned.

On Python 3.9 and 3.10 mock.patch resolves the dotted path with getattr,
and lean.commands.live is the click group there, not the package.
@jhonabreul

Copy link
Copy Markdown
Collaborator

Pushed eb2f4ea for the Python 3.9 failure: mock.patch with a dotted path resolves lean.commands.live to the click group there, since lean/commands/__init__.py imports the group under the package's name. The test now patches the module object instead. Verified on 3.9 and 3.14.

@Martin-Molinero
Martin-Molinero merged commit 97319f0 into QuantConnect:master Oct 15, 2026
38 checks passed
@Amadeus-22

Copy link
Copy Markdown
Contributor Author

Thanks for the follow-ups, @jhonabreul. I read d2c9a37, 96ae80c and eb2f4ea: matching only the timestamped deployment entries covers the --output live/ case I missed, and the notes on the Windows-only timestamp conversion and the Python 3.9 mock.patch behavior are useful for the next tests I write.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

live deploy fails when the project's live directory contains a non-deployment entry

3 participants