feature: add TerminalLink IsCfdTrade order property - #9689
Merged
Martin-Molinero merged 3 commits intoAug 13, 2026
Conversation
AlexCatarino
force-pushed
the
feature/emsx-cfd-flag
branch
from
August 12, 2026 13:15
bffeabc to
31d4e42
Compare
Adds IsCfdTrade to TerminalLinkOrderProperties so an algorithm can book an EMSX order as a contract for differences instead of a regular trade. The companion Lean.Brokerages.TerminalLink PR maps it to EMSX_CFD_FLAG on the CreateOrderAndRouteEx request. On the EMSX trading ticket this is the "Booking Type" drop-down, whose options are Regular, CFD and TRS. Only the CFD booking has an element in the EMSX API (EMSX_CFD_FLAG, "0"/"1"); there is no booking-type element and nothing for TRS in Bloomberg's element reference, so the property is a bool rather than a three-valued enum. Defaults to false, which is the EMSX default and the value for which the brokerage sends no flag at all, leaving existing orders on the wire byte-identical. The property is a pass through over a new AdditionalProperties dictionary of EMSX element name to value, following BloombergFixOrderProperties, so the typed property and the raw element cannot disagree. The dictionary starts empty and is add/remove only - it has no setter, since a plain Python dict is not convertible to Dictionary<string, string> and swapping the instance would detach the typed properties from their store. Callers reset it with clear(). Clone deep copies it so the locate cleanup in BrokerageExtensions, which edits a copy, cannot reach the algorithm's own instance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AlexCatarino
force-pushed
the
feature/emsx-cfd-flag
branch
from
August 12, 2026 21:24
31d4e42 to
471889f
Compare
Addresses the review suggestion to make IsCfdTrade a pass through like the
Bloomberg FIX properties do, over a new AdditionalProperties dictionary keyed
by EMSX element name, so the typed property and the raw element are one store
and cannot disagree.
Uses BaseExtendedDictionary rather than Dictionary so the dictionary behaves
like a Python dict. pythonnet has no conversion from a plain dict, so
properties.additional_properties = { "EMSX_CFD_FLAG": "1" }
throws at runtime; update() takes a PyObject and gives callers the bulk load
they reach for, alongside get(), pop(), setdefault() and clear(). Both the
working idiom and the failing one are covered by tests.
Clone deep copies the dictionary. OrderProperties.Clone is a MemberwiseClone,
which would share it, and BrokerageExtensions.RemoveLocateFromNonShortOrder
clones precisely so its edits never reach the instance the algorithm holds on
to; there is a regression test.
Setting IsCfdTrade to false removes the entry rather than writing "0", so the
dictionary only ever carries what is explicitly on and an untouched order goes
out exactly as before.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gives the FIX custom tags the same Python dict semantics TerminalLink just got. update() takes a PyObject, so a Python algorithm can bulk load its tags from a plain dict, which plain assignment cannot do; get(), pop(), setdefault() and clear() come along with it. Clone copies into a new instance as before. BaseExtendedDictionary implements IDictionary but not IReadOnlyDictionary, so the GetValueOrDefault extension no longer resolves. The Bloomberg locate passthroughs read through a GetTag helper instead, mirroring SetTag, and the transaction handler test uses a local helper of its own. Note that the null conditional form cannot be used with out var - the call is conditional, so the variable is not definitely assigned. The subclasses BloombergFixOrderProperties, TradingTechnologiesOrderProperties and the obsolete FixOrderProperites inherit the property and Clone unchanged; InteractiveBrokersFixOrderProperties extends OrderProperties despite the name and is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin-Molinero
approved these changes
Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds
IsCfdTradetoTerminalLinkOrderPropertiesso an algorithm can book an EMSX order as a contract for differences instead of a regular trade.On the EMSX trading ticket this is the Booking Type drop-down, whose options are Regular, CFD and TRS:
EMSX_CFD_FLAG, aSTRINGORDER-level field taking"0"/"1".CreateOrderAndRouteExsamples.EMSX_ASSET_CLASSis likewise limited toEQTY/OPT/FUT/MULTILEG_OPT.Hence a
boolrather than a three-valued enum. It defaults tofalse, which is the EMSX default and the value for which the brokerage sends no flag at all, so existing orders are unchanged on the wire. The XML summary is Bloomberg's own wording for the element.AdditionalProperties
IsCfdTradeis a pass through over a newAdditionalPropertiesdictionary of EMSX element name → value, followingBloombergFixOrderProperties, so the typed property and the raw element are one store and cannot disagree. The brokerage PR drains the dictionary onto the request, which also lets an algorithm set any EMSX element without waiting on a Lean release.Two deliberate differences from
FixOrderProperties:Dictionary<string, string>— pythonnet raises "'dict' value cannot be converted" — and the only way to assign wholesale would beDictionary[str, str]()from Python, which is not an idiom we want to document. Swapping the instance would also detach the typed properties from their store. The dictionary starts empty and is add/remove only;clear()resets it, and works from both C# and Python (covered by a test).Clone()is overridden to deep copy it.OrderProperties.Clone()is aMemberwiseClone, which would share the dictionary — andBrokerageExtensions.RemoveLocateFromNonShortOrderclones precisely so its edits never reach the caller's instance. There is a regression test.Possible follow-up:
ExtendedDictionary<TKey, TValue>would give the dictionary proper Python semantics; it is abstract, so it would need a concrete<string, string>subclass. Out of scope here, raising it as an option.Related Issue
QuantConnect/Lean.Brokerages.TerminalLink#135, companion PR QuantConnect/Lean.Brokerages.TerminalLink#136.
Requires Documentation Change
Yes —
IsCfdTradeandAdditionalPropertiesshould be listed with the other TerminalLink order properties.Tests
TerminalLinkOrderPropertiesTests, 10 passing, covering the default, theCloneisolation, and the Python surface:is_cfd_trade, writing an entry throughadditional_properties,clear(), and that the dictionary cannot be replaced.🤖 Generated with Claude Code