Skip to content

resolve subscriber#1000

Open
brettelliot wants to merge 3 commits intodevfrom
be-resolve-subscriber
Open

resolve subscriber#1000
brettelliot wants to merge 3 commits intodevfrom
be-resolve-subscriber

Conversation

@brettelliot
Copy link
Copy Markdown
Collaborator

@brettelliot brettelliot commented Apr 28, 2026

This makes a few fixes to prevent "subscriber not found" errors. The Tradier broker polls Tradier every 5 seconds. We can get into situations where we poll before the strategy's name is added as a subscriber. These fixes attempt to prevent that.

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of order and trade event handling when strategy information is unavailable or incomplete.
    • Enhanced order reconciliation with broker to better match orders with strategies, including handling of order identifiers with formatting variations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

Walkthrough

The changes enhance subscriber resolution logic for order and trade event dispatching. A helper function in the broker module enables event dispatch when strategy context is missing by defaulting to a sole subscriber. The Tradier broker integration extends this with strategy name computation and backfilling logic during order reconciliation.

Changes

Cohort / File(s) Summary
Subscriber Resolution
lumibot/brokers/broker.py
Adds a helper method to resolve subscribers when order.strategy or strategy_name is falsy, enabling fallback to the sole registered subscriber. Updates event dispatch points (new order, canceled order, partial fill, full fill, and error handling) to use this resolver.
Polling and Order Reconciliation
lumibot/brokers/tradier.py
Computes strategy_name once per poll cycle using self._strategy_name or deriving from sole subscriber. During order reconciliation, backfills missing stored_order.strategy by matching subscriber names against order tags (handling Tradier's underscore-to-hyphen transformations), with fallback to sole subscriber name.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A helper spring forth, wise and true,
When strategy fades to empty view,
One subscriber stands, a noble friend,
To guide each order from start to end,
Poll by poll, with careful care,
No lost trades floating in the air!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'resolve subscriber' is related to the main changes, which address subscriber resolution and handling missing subscriber scenarios in event dispatch and order polling.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch be-resolve-subscriber

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Pylint (4.0.5)
lumibot/brokers/tradier.py

************* Module pylintrc
pylintrc:1:0: F0011: error while parsing the configuration: File contains no section headers.
file: 'pylintrc', line: 1
'known-third-party=lumibot' (config-parse-error)
[
{
"type": "convention",
"module": "lumibot.brokers.tradier",
"obj": "",
"line": 30,
"column": 0,
"endLine": null,
"endColumn": null,
"path": "lumibot/brokers/tradier.py",
"symbol": "line-too-long",
"message": "Line too long (116/100)",
"message-id": "C0301"
},
{
"type": "convention",
"module": "lumibot.brokers.tradier",
"obj": "",
"line": 31,
"column": 0,
"endLine": null,
"endColumn": null,
"path": "lumibot/brokers/tradier.py",
"symbol": "line-too-long",
"message": "Line too long (116/100)",
"message-id": "C0301"
},
{
"type": "convention",
"module": "lumibot.brokers.tradier",

... [truncated 79790 characters] ...

"line": 22,
    "column": 0,
    "endLine": 22,
    "endColumn": 51,
    "path": "lumibot/brokers/tradier.py",
    "symbol": "wrong-import-order",
    "message": "first party import \"lumibot.tools.lumibot_logger.get_logger\" should be placed before local import \"broker.Broker\"",
    "message-id": "C0411"
},
{
    "type": "convention",
    "module": "lumibot.brokers.tradier",
    "obj": "",
    "line": 23,
    "column": 0,
    "endLine": 23,
    "endColumn": 50,
    "path": "lumibot/brokers/tradier.py",
    "symbol": "wrong-import-order",
    "message": "first party import \"lumibot.trading_builtins.PollingStream\" should be placed before local import \"broker.Broker\"",
    "message-id": "C0411"
}

]

lumibot/brokers/broker.py

************* Module pylintrc
pylintrc:1:0: F0011: error while parsing the configuration: File contains no section headers.
file: 'pylintrc', line: 1
'known-third-party=lumibot' (config-parse-error)
[
{
"type": "convention",
"module": "lumibot.brokers.broker",
"obj": "",
"line": 30,
"column": 0,
"endLine": null,
"endColumn": null,
"path": "lumibot/brokers/broker.py",
"symbol": "line-too-long",
"message": "Line too long (105/100)",
"message-id": "C0301"
},
{
"type": "convention",
"module": "lumibot.brokers.broker",
"obj": "",
"line": 129,
"column": 0,
"endLine": null,
"endColumn": null,
"path": "lumibot/brokers/broker.py",
"symbol": "line-too-long",
"message": "Line too long (105/100)",
"message-id": "C0301"
},
{
"type": "convention",
"module": "lumibot.brokers.broker",

... [truncated 116424 characters] ...

    "type": "warning",
    "module": "lumibot.brokers.broker",
    "obj": "Broker._is_continuous_market",
    "line": 1663,
    "column": 12,
    "endLine": 1663,
    "endColumn": 35,
    "path": "lumibot/brokers/broker.py",
    "symbol": "attribute-defined-outside-init",
    "message": "Attribute '_market_type_cache' defined outside __init__",
    "message-id": "W0201"
},
{
    "type": "refactor",
    "module": "lumibot.brokers.broker",
    "obj": "Broker",
    "line": 108,
    "column": 0,
    "endLine": 108,
    "endColumn": 12,
    "path": "lumibot/brokers/broker.py",
    "symbol": "too-many-public-methods",
    "message": "Too many public methods (52/20)",
    "message-id": "R0904"
}

]


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lumibot/brokers/broker.py (1)

2298-2302: ⚠️ Potential issue | 🔴 Critical

Use correct pattern for colored error logging: colored() wraps the message, not passed as kwarg to error().

Line 2302 passes color= as a keyword argument to error(), but this parameter is silently ignored by the standard logger. The color formatting is ineffective, and the pattern is inconsistent with the correct usage throughout the codebase (e.g., line 2310 in the same file).

Proposed fix
-            self.logger.error(f"Subscriber {order.strategy} not found", color="red")
+            self.logger.error(colored(f"Subscriber {order.strategy} not found", "red"))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lumibot/brokers/broker.py` around lines 2298 - 2302, The logger.error call is
incorrectly passing color="red" as a kwarg (which standard logging ignores);
update the else branch where self._resolve_subscriber(order.strategy) returns
None to wrap the message with colored(...) instead of passing color=, e.g. build
the string "Subscriber {order.strategy} not found" using colored(...) and pass
that single formatted string to self.logger.error; ensure you reference the same
symbols (self._resolve_subscriber, order.strategy, self.logger.error) and remove
the color= keyword usage to match the pattern used elsewhere (e.g., the file's
other logging lines).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lumibot/brokers/tradier.py`:
- Around line 1311-1315: Add regression tests and brief documentation/comments
for the new strategy-resolution behavior around _strategy_name and _subscribers:
write unit tests that exercise the code path that sets strategy_name from
self._subscribers when _strategy_name is falsy and len(self._subscribers)==1,
tests that validate tag-to-subscriber repair (including normalization of
underscores/non-alphanumeric chars) and tests that verify unresolved tags fall
back to the sole subscriber; add these tests invoking the method that consumes
raw_orders and calls _parse_broker_order_dict (use the same inputs used by the
existing polling code) and assert the resolved strategy_name and subscriber
attribution; update docs/ with a short note about the invariants and add an
inline comment near the resolution logic (the block referencing _strategy_name,
_subscribers, and _parse_broker_order_dict and the tag-repair code around lines
~1341-1354) explaining the why/invariants for future readers.

---

Outside diff comments:
In `@lumibot/brokers/broker.py`:
- Around line 2298-2302: The logger.error call is incorrectly passing
color="red" as a kwarg (which standard logging ignores); update the else branch
where self._resolve_subscriber(order.strategy) returns None to wrap the message
with colored(...) instead of passing color=, e.g. build the string "Subscriber
{order.strategy} not found" using colored(...) and pass that single formatted
string to self.logger.error; ensure you reference the same symbols
(self._resolve_subscriber, order.strategy, self.logger.error) and remove the
color= keyword usage to match the pattern used elsewhere (e.g., the file's other
logging lines).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad4646bc-410a-43da-bbd9-8aa296188b36

📥 Commits

Reviewing files that changed from the base of the PR and between 2d51f9c and 75b8bdf.

📒 Files selected for processing (2)
  • lumibot/brokers/broker.py
  • lumibot/brokers/tradier.py

Comment on lines +1311 to +1315
strategy_name = self._strategy_name
if not strategy_name and len(self._subscribers) == 1:
strategy_name = self._subscribers[0].name
for order_row in raw_orders:
order = self._parse_broker_order_dict(order_row, strategy_name=self._strategy_name)
order = self._parse_broker_order_dict(order_row, strategy_name=strategy_name)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add regression tests for the new strategy-resolution behavior.

This changes core polling attribution behavior (sole-subscriber fallback + tag-based strategy repair), but there’s no accompanying regression coverage in the provided changes. Please add tests covering at least:

  • missing strategy_name with exactly one subscriber,
  • tag-to-subscriber repair (including underscore/non-alnum normalization),
  • unresolved tag fallback to sole subscriber.

As per coding guidelines "Document and test behavioral changes: update relevant docs in docs/ and add regression tests in the same commit; add comments explaining 'why/invariants' for non-obvious logic."

Also applies to: 1341-1354

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lumibot/brokers/tradier.py` around lines 1311 - 1315, Add regression tests
and brief documentation/comments for the new strategy-resolution behavior around
_strategy_name and _subscribers: write unit tests that exercise the code path
that sets strategy_name from self._subscribers when _strategy_name is falsy and
len(self._subscribers)==1, tests that validate tag-to-subscriber repair
(including normalization of underscores/non-alphanumeric chars) and tests that
verify unresolved tags fall back to the sole subscriber; add these tests
invoking the method that consumes raw_orders and calls _parse_broker_order_dict
(use the same inputs used by the existing polling code) and assert the resolved
strategy_name and subscriber attribution; update docs/ with a short note about
the invariants and add an inline comment near the resolution logic (the block
referencing _strategy_name, _subscribers, and _parse_broker_order_dict and the
tag-repair code around lines ~1341-1354) explaining the why/invariants for
future readers.

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.

1 participant