Skip to content

TerminalLinkBrokerageModel rejects SecurityType.Index orders even with EMSX CFD flag set #9747

Description

@AlexCatarino

Summary

TerminalLinkBrokerageModel.CanSubmitOrder rejects every order on a
SecurityType.Index security, even when the order is explicitly marked as an
EMSX CFD trade (TerminalLinkOrderProperties.IsCfdTrade = true). This blocks a
legitimate Bloomberg EMSX workflow: submitting a custom basket (e.g. a Morgan
Stanley basket swap) whose market data is delivered via B-Pipe as an index, by
providing the index ticker directly in the EMSX security field and booking the
ticket as a CFD/swap. In a standard (non-LEAN) EMSX ticket this is a normal,
supported booking flow.

Evidence

  • Common/Brokerages/TerminalLinkBrokerageModel.cs:27-33 -- _supportedSecurityTypes
    is { Equity, Option, IndexOption, Future }; Index is absent, so
    CanSubmitOrder (line 60) always returns false with NotSupported /
    UnsupportedSecurityType for any Index order, regardless of order properties.
  • Tests/Common/Brokerages/TerminalLinkBrokerageModelTests.cs:43-49 -- the
    existing test suite documents this as deliberate: "Index is data-only on
    TerminalLink", with an explicit CannotSubmitOrder_ForUnsupportedSecurityTypes
    case for SPX/SecurityType.Index. That assumption (index = data-only, never
    order-eligible) is what this ticket contradicts for the CFD/basket-swap case.
  • Common/Orders/TerminalLinkOrderProperties.cs:102-111 -- IsCfdTrade is an
    order-level flag (EMSX_CFD_FLAG) that is explicitly documented as
    "applicable to trades on an order level, and does not populate on a per
    security basis" -- i.e. the CFD booking type is independent of the security's
    type, by design.
  • QuantConnect.TerminalLink/TerminalLinkBrokerage.cs:395-429 -- PlaceOrder
    already sends EMSX_CFD_FLAG (via SetAdditionalProperties, populated from
    IsCfdTrade) on the outgoing EMSX request, so the brokerage adapter itself
    is fully wired for a CFD-flagged order on any security type. The block happens
    earlier, at the engine-level CanSubmitOrder pre-flight check, before
    PlaceOrder is ever reached.
  • QuantConnect.TerminalLink/TerminalLinkSymbolMapper.cs:468-479 -- Index
    ticker resolution (e.g. "MSXXAI Index" -> Symbol.Create(ticker, SecurityType.Index, market)) is already implemented, so the symbol side of
    this workflow works; only the brokerage-model gate blocks the order.

Repro

Reported live (conv 215475638579180, support plan Institution, deploy
L-60ec350cc89032ff271d9a04ecc009b8, 2026-08-25 14:37:36 UTC):

New Order Event: ... Symbol: MSXXAI Status: Invalid Quantity: 1 Message:
BrokerageModel declared unable to submit order: [1] Warning - Code:
NotSupported - The TerminalLinkBrokerageModel does not support Index security
type.

The algorithm added MSXXAI Index (a custom Morgan Stanley basket, market data
via B-Pipe as an index) as an Index security and submitted an order with
TerminalLinkOrderProperties { IsCfdTrade = true }, intending to route it as a
CFD/swap through EMSX -- the same thing a standard EMSX ticket allows by typing
the index ticker into the security field.

Proposed change

Relax TerminalLinkBrokerageModel._supportedSecurityTypes (or the
CanSubmitOrder check specifically) to allow SecurityType.Index at least when
order.Properties is TerminalLinkOrderProperties { IsCfdTrade: true }, so a
CFD-flagged index/basket order reaches PlaceOrder the same way a normal
EMSX ticket would accept it. Whether to gate this strictly on IsCfdTrade or
open Index up generally is an engineering call -- the existing
"Index is data-only" test comment suggests the restriction was written before
this CFD/basket-swap use case existed, not as a deliberate rejection of it.

Open questions

  • Does EMSX itself require the CFD flag to accept an index ticker in the
    security field, or does it accept a plain index ticket too (customer's
    description of "a normal EMSX ticket" suggests the ticker itself is always
    accepted; the CFD flag only changes the booking type)? If the latter, the fix
    may not need to be conditioned on IsCfdTrade at all.
  • Should IndexOption's underlying Index security (already added implicitly
    for IndexOption support) be distinguished from a directly-tradable Index like
    this basket, or is a blanket allow sufficient?

Intercom conversation: 215475638579180

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions