agentleFS
QuantConnectQuantConnect/Documentation/skills/python/debug-algorithm/SKILL.md

debug-algorithm

Skill268 starsChanged 48 days agoApache-2.0View on GitHub

Diagnoses QuantConnect Python (.py) and C# (.cs) algorithm failures: runtime exceptions and zero-trade backtests. Invoked by other agents the moment an algorithm throws a runtime error or completes a backtest with 0 orders. Walks an ordered checklist to the root cause without hiding it. Trigger phrases: "runtime error", "stack trace", "0 orders", "no trades", "flat equity curve", "unknown property", "AttributeError", "KeyNotFoundException", "wasn't found in the DataDictionary", "insufficient buying power", "indicator not ready", "debug the algorithm".

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never introduce pytry/exceptcstry/catch or pyhasattr/getattr/setattr/isinstancecsreflection.

    line 21
  2. Distinctive:

    Read the actual message and line.

    line 42
  3. Distinctive:

    Stop at the first that applies.

    line 62
  4. Very specific:

    Do not find a property or method by pyhasattr/getattrcsreflection.

    line 103
  5. Distinctive:

    No banned pattern (Section 0).

    line 122
  6. Very specific:

    No check added/tightened to mask 0 trades.

    line 128

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/debug-algorithm - QuantConnect Cross-Language Debugging

Invoked on a runtime error or a 0-order backtest. Work top to bottom. Find the real cause; never hide it. Same rules for main.py and main.cs.

0. Never add error-hiding patterns

Never introduce pytry/exceptcstry/catch or pyhasattr/getattr/setattr/isinstancecsreflection. They hide the exact failure. If existing code wraps the failing region in one, remove it, re-run, read the real exception, then continue. Only add an if check to skip a known, expected case (such as a header line) by testing that exact condition. Adding a check just to make a crash or 0 trades go away is not a fix; fix the cause.

1. Shorten the backtest, then find the failure type

Record the original pyset_start_date/set_end_datecsSetStartDate/SetEndDate and universe, then shrink both: the smallest window that still reproduces the failure (runtime error: a span around the error date; 0 trades: 3 to 6 months), and the universe to a small fixed symbol list or tight filter. Only after the fix gives non-zero orders with no runtime error, restore the original dates and universe and run ONE final full-period backtest to confirm. Match the failure type:

  • Runtime exception -> Section 2.
  • 0 orders / flat equity -> Section 3.

2. Runtime exception

Read the actual message and line; never guess.

  • Unknown property or method / AttributeError / "no attribute" -> Section 4.
  • KeyNotFound / "wasn't found in the DataDictionary": find WHY the key is absent first. Custom/alt data (add_data) has its OWN symbol (the return value), not the equity symbol; reading alt data with the equity symbol is the usual cause. Key by add_data(...).symbol; field names from the QC docs page (Section 4), never getattr. Skipping a wrong key with a check just turns the crash into 0 trades (Section 3). symbol in data is right only for a real fillforward gap on a correct key.
  • None / null price: seed_initial_prices only looks back 3 days; keep only securities where security.price is set.
  • Insufficient buying power: reduce exposure, then derivative sizing, then raise free_portfolio_value_percentage; add liquidate_existing_holdings=True; if a 9:00 schedule still fails, move it to 9, 31 (sizes on intraday price).

3. 0 trades / 0 orders

Stop at the first that applies. NEVER add or tighten a check here.

  1. Selection too strict OR too loose (the usual flat equity / silent-fail cause).
    • Too strict: a long chain of if ...: continue checks drops every candidate, so set_holdings runs with an empty list -> 0 orders / flat equity.
    • Too loose: the filter passes a very large set (e.g. 1000+) into an equal-weight set_holdings; LEAN cannot size that many positions and silently places no orders. Measure with self.log(...) in the rebalance/filter: log the count passing each check and the final selected count. Find the one check responsible, then loosen or tighten just it. Common cause: data an earlier bug left empty (e.g. a signal dict from the Section 2 wrong-symbol bug), or thresholds too strict to ever happen together. Logging rules: never set_runtime_statistic or the Object Store; never self.log in on_data or an often-firing scheduled event (it floods); if unavoidable there, gate it to the first N calls with a counter.
  2. Schedule / frequency mismatch:
    • Daily-resolution data with an intraday TimeRule (e.g. time_rules.after_market_open) fires before the daily bar is delivered, so the rebalance reads stale/empty data. With daily data schedule via self.date_rules... + self.time_rules.at(8, 0); use an intraday TimeRule only with minute/hour data.
    • Rebalance reads self._universe.selected on a different/earlier frequency than the universe updates, so it sees an empty set. Align both to the same DateRule, or drive the rebalance from on_securities_changed.
  3. Universe empty / wrong Universe.UNCHANGED return (only a filter that just stores symbols and selects nothing returns it; a real selection returns a list).
  4. Securities dropped for missing price (see Section 2).
  5. Indicators never ready: automatic_indicator_warm_up = True set BEFORE any factory call; feed manual indicators/consolidators in initialize via a history loop; warm-up length fits the rebalance frequency (weekly 14d, monthly or slower 45d). Futures/continuous contracts need this.

4. Unknown property or method

Do not find a property or method by pyhasattr/getattrcsreflection. Find the real property/field name on the dataset's or type's QC docs page, then use it directly. Quick rules:

  • Alt-data fields (headline, body, sentiment, etc.) come from that dataset's page, never from getattr guessing.
  • Comparing indicators: use indicator.current.value. Direct object comparison only works when both are the same indicator type; different types (or an indicator vs a sub-indicator) need the explicit .current.value. Previous value: indicator.previous.value, not .window[0].
  • Fundamental data missing: np.isnan(value), never != 0.
  • Yesterday's daily OHLC: security.session (set .size; index [1] is yesterday). Change one access at a time, then re-run.

5. Checklist

  1. No banned pattern (Section 0).
  2. Original dates + universe recorded before shrinking.
  3. Fix targets the real exception line, not a guess.
  4. Alt/custom data keyed by the add_data symbol; presence checks only for real fillforward gaps.
  5. Unknown properties/fields taken from the QC docs page, not guessed.
  6. No check added/tightened to mask 0 trades; cause found via self.log; selection not so large set_holdings silently no-ops (Section 3).
  7. Universe and rebalance same frequency; schedule matches data (daily not on an intraday TimeRule, DateRule symbol subscribed); indicators warmed; no buying-power rejection.
  8. Original period + universe restored; ONE final backtest confirms non-zero orders and no error.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.