Skip to content

Polish the order surface: numeric OrderFee, flat combo group ids, tag tolerance and notional targeting - #9676

Draft
jhonabreul wants to merge 1 commit into
QuantConnect:masterfrom
jhonabreul:feature-order-surface-polish
Draft

Polish the order surface: numeric OrderFee, flat combo group ids, tag tolerance and notional targeting#9676
jhonabreul wants to merge 1 commit into
QuantConnect:masterfrom
jhonabreul:feature-order-surface-polish

Conversation

@jhonabreul

@jhonabreul jhonabreul commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Description

Python algorithms repeatedly crash on the first names they reach for on the order surface. For example:

'OrderFee' object has no attribute 'amount'
Trying to perform a summation ... between 'OrderFee' and 'OrderFee' objects throws a TypeError
'ComboLimitOrder' object has no attribute 'group_order_manager_id'
self.liquidate("EOD close") -> overload dump (the tag binds to the symbol slot)

The change adds the flat shortcuts and operators these calls expect:

  • OrderFee.Amount / Currency shortcuts, plus arithmetic and comparison operators delegating to Value.Amount, so fee1 + fee2, sum(fees) and fee > 0 work from Python.
  • OrderEvent.OrderFeeAmount, OrderEvent.GroupId and Order.GroupOrderManagerId shortcuts.
  • ComboOrderTicket returned by the combo order methods: holds the leg tickets and aggregates the group (Tickets, GroupOrderManagerId, Filled). It subclasses List<OrderTicket>, so existing iteration/indexing keeps working in both languages.
  • market_order(symbol, 10, "entry"): Python-only overload accepting the tag in the third positional slot.
  • Liquidate(string): resolves known tickers; unknown strings fail with a prescriptive error (pointing at Liquidate(tag: ...)) instead of a silent no-op or an overload dump.
  • OrderTargetNotional(symbol, targetNotional): market order adjusting holdings to an absolute notional; handles contract multipliers, lot-size rounding, and returns null when already at target.

Deferred: an OrderStatus.REJECTED alias for INVALID (duplicate enum values change either the log or the JSON surface), and float(order_fee) (needs an interop-layer __float__ slot; the Amount shortcut covers it).

Related Issue

N/A

Motivation and Context

These are the exact names and operations users try first, and each was a recurring source of failed backtests.

Requires Documentation Change

The new public members are candidates for documentation once merged.

How Has This Been Tested?

  • New OrderSurfaceShortcutsRegressionAlgorithm (C# + Python): asserts every shortcut, the combo ticket aggregation, the positional tag, the Liquidate error and OrderTargetNotional. Identical statistics in both languages.
  • New unit tests: OrderFeeTests (shortcuts, operators, JSON shape unchanged), ComboOrderTicketTests, OrderEventTests/OrderTests shortcut cases, AlgorithmTradingTests (Liquidate and OrderTargetNotional math incl. futures multiplier).
  • A scratch Python probe reproduced all the error signatures on master and confirmed them fixed after the change.
  • Suites: Tests.Common.Orders 994, Tests.Algorithm 12,719, Tests.Python 1,297, combo/liquidate regression algorithms 24 — all passed.

Compatibility note: the combo order methods now return ComboOrderTicket (a List<OrderTicket> subclass — source compatible), and Liquidate with an unknown ticker now raises instead of warning-and-ignoring.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

… tolerance and notional targeting

- OrderFee: flat Amount/Currency shortcuts plus arithmetic and comparison
  operators delegating to Value.Amount, surfaced in Python as
  __add__/__radd__/__gt__/... via pythonnet's operator mapping
- OrderEvent.OrderFeeAmount and OrderEvent.GroupId shortcuts
- Order.GroupOrderManagerId shortcut for combo orders
- ComboOrderTicket: non-generic List<OrderTicket> returned by the combo
  order methods with Tickets/GroupOrderManagerId/Filled aggregation
- MarketOrder(PyObject, decimal, string): accepts the tag in the third
  positional slot from Python
- Liquidate(string): resolves known tickers, fails pointing to the tag
  parameter for unknown strings such as a tag slipped into the symbol slot
- OrderTargetNotional: targets an absolute notional value including the
  contract multiplier, rounding to the security lot size
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