orionapi 2.26.0__tar.gz → 2.28.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "2.
|
|
1
|
+
__version__ = "2.28.0"
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
@@ -56,10 +56,16 @@ TRADE_INSTANCE_SUBTYPES = {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
# TradingApplication mappings for the v2 /TradeOrder/Trades endpoints.
|
|
59
|
-
# Not published in the Swagger (which lists the ints with no names)
|
|
60
|
-
# 2026-07-28 from the API's own rejection messages
|
|
61
|
-
# not supported.")
|
|
59
|
+
# Not published in the Swagger (which lists the ints with no names). Names 0-10
|
|
60
|
+
# and 12-18 were recovered 2026-07-28 from the API's own rejection messages
|
|
61
|
+
# ("Trade Application <Name> is not supported."); 11 is QuickTrades, confirmed
|
|
62
|
+
# 2026-08-03 by Orion support and verified live (the string "QuickTrades" and the
|
|
63
|
+
# int 11 return identical results). Only 11 creates trade orders -- see
|
|
62
64
|
# EclipseV2.create_trades.
|
|
65
|
+
#
|
|
66
|
+
# These names are also accepted as *strings* in the ``application`` field, e.g.
|
|
67
|
+
# ``{"application": "QuickTrades"}``. A name outside this set is rejected with
|
|
68
|
+
# 400 "Error converting value ... to type 'OAS.Eclipse.Core.Enums.TradingApplication'".
|
|
63
69
|
TRADING_APPLICATIONS = {
|
|
64
70
|
0: "BuySell",
|
|
65
71
|
1: "CashNeeds",
|
|
@@ -72,7 +78,7 @@ TRADING_APPLICATIONS = {
|
|
|
72
78
|
8: "TaxLossHarvesting",
|
|
73
79
|
9: "TickerSwap",
|
|
74
80
|
10: "TradeToTargetPercent",
|
|
75
|
-
11: "
|
|
81
|
+
11: "QuickTrades",
|
|
76
82
|
12: "TacticalTrades",
|
|
77
83
|
13: "PartialShare",
|
|
78
84
|
14: "(unnamed, accepted but creates nothing)",
|
|
@@ -86,7 +92,12 @@ TRADING_APPLICATIONS = {
|
|
|
86
92
|
# POST /api/v2/TradeOrder/Trades. Every other value except 14 returns
|
|
87
93
|
# 400 "Trade Application <Name> is not supported."; 14 returns 200 with an
|
|
88
94
|
# empty ``tradeId`` list and creates nothing. Live-verified 2026-07-28.
|
|
89
|
-
|
|
95
|
+
TRADING_APPLICATION_QUICK_TRADES = 11
|
|
96
|
+
|
|
97
|
+
# Deprecated alias. 2.26.0 shipped this as TRADING_APPLICATION_MANUAL on the
|
|
98
|
+
# mistaken belief that 11 was named "ManualTrade"; the API rejects that name.
|
|
99
|
+
# Kept so 2.26.0/2.27.0 callers keep working -- the value is unchanged.
|
|
100
|
+
TRADING_APPLICATION_MANUAL = TRADING_APPLICATION_QUICK_TRADES
|
|
90
101
|
|
|
91
102
|
# Set-Aside Cash Constants (from Eclipse API)
|
|
92
103
|
CASH_TYPE_DOLLAR = 1
|
|
@@ -159,6 +170,31 @@ BILLING_BILL_TYPES = [
|
|
|
159
170
|
"AdvanceCreditDebit",
|
|
160
171
|
]
|
|
161
172
|
|
|
173
|
+
# Fields of the Orion API ReceiveableSummaryDto, the body of
|
|
174
|
+
# POST /Billing/SyncCashtoEclipse. Identical to the CashFundingGridDto rows
|
|
175
|
+
# returned by get_cash_funding(), except the grid's "id" is "accountId" here.
|
|
176
|
+
RECEIVABLE_SUMMARY_FIELDS = (
|
|
177
|
+
"accountId",
|
|
178
|
+
"registrationName",
|
|
179
|
+
"registrationId",
|
|
180
|
+
"fundFamily",
|
|
181
|
+
"productName",
|
|
182
|
+
"moneyMarketBalance",
|
|
183
|
+
"balanceDue",
|
|
184
|
+
"difference",
|
|
185
|
+
"payMethod",
|
|
186
|
+
"clientId",
|
|
187
|
+
"clientLastName",
|
|
188
|
+
"clientName",
|
|
189
|
+
"accountType",
|
|
190
|
+
"accountNumber",
|
|
191
|
+
"managementStyle",
|
|
192
|
+
"accountIsActive",
|
|
193
|
+
"representativeName",
|
|
194
|
+
"feeReqSrc",
|
|
195
|
+
"instanceType",
|
|
196
|
+
)
|
|
197
|
+
|
|
162
198
|
|
|
163
199
|
class OrionAPIError(Exception):
|
|
164
200
|
"""Base exception for Orion API errors."""
|
|
@@ -178,6 +214,17 @@ class NotFoundError(OrionAPIError):
|
|
|
178
214
|
pass
|
|
179
215
|
|
|
180
216
|
|
|
217
|
+
class AmbiguousAccountError(OrionAPIError):
|
|
218
|
+
"""Raised when an account search matches more than one account.
|
|
219
|
+
|
|
220
|
+
The message lists the candidate accounts (id, name, accountNumber) so the
|
|
221
|
+
caller can retry with an exact internal id, a full account number, or the
|
|
222
|
+
deliberate fuzzy workflow (``search_accounts_number_and_name``).
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
|
|
181
228
|
class RateLimiter:
|
|
182
229
|
"""Thread-safe rate limiter to prevent API abuse.
|
|
183
230
|
|
|
@@ -1655,10 +1702,13 @@ class OrionAPI(BaseAPI):
|
|
|
1655
1702
|
if not isinstance(take, int) or take < 1:
|
|
1656
1703
|
raise ValueError("take must be a positive integer")
|
|
1657
1704
|
|
|
1705
|
+
# forecast is a boolean: Orion's own docs claim "1 = Forecast Bill,
|
|
1706
|
+
# 0 = Live Bill", but the endpoint 400s on 0/1 and only accepts
|
|
1707
|
+
# true/false.
|
|
1658
1708
|
params = {
|
|
1659
1709
|
"startDate": start_date,
|
|
1660
1710
|
"endDate": end_date,
|
|
1661
|
-
"forecast":
|
|
1711
|
+
"forecast": "true" if is_forecast else "false",
|
|
1662
1712
|
"take": take,
|
|
1663
1713
|
}
|
|
1664
1714
|
if skip > 0:
|
|
@@ -1699,6 +1749,42 @@ class OrionAPI(BaseAPI):
|
|
|
1699
1749
|
res = self.api_request(url, requests.post)
|
|
1700
1750
|
return res.json()
|
|
1701
1751
|
|
|
1752
|
+
def sync_cash_to_eclipse(self, account):
|
|
1753
|
+
"""Export one cash funding row to Eclipse as a cash set-aside.
|
|
1754
|
+
|
|
1755
|
+
This is the API equivalent of the Cash Funding grid's export action:
|
|
1756
|
+
Orion creates (or updates) a set-aside in Eclipse for the account's
|
|
1757
|
+
balance due, so the fee cash is reserved from trading.
|
|
1758
|
+
|
|
1759
|
+
Orion documents this as a draft endpoint that takes a single account
|
|
1760
|
+
per call, so exporting a whole report means looping over the rows of
|
|
1761
|
+
get_cash_funding().
|
|
1762
|
+
|
|
1763
|
+
Args:
|
|
1764
|
+
account: A cash funding row as returned by get_cash_funding().
|
|
1765
|
+
The row's ``id`` is the Orion account ID and is sent as
|
|
1766
|
+
``accountId``. A dict already keyed ``accountId`` is also
|
|
1767
|
+
accepted. Keys outside ReceiveableSummaryDto are dropped.
|
|
1768
|
+
|
|
1769
|
+
Returns:
|
|
1770
|
+
dict: The created/updated Eclipse set-aside
|
|
1771
|
+
(EclipseCashFundingResponse) with id, accountId, cashAmount,
|
|
1772
|
+
cashAmountTypeId, description, expirationTypeId, etc.
|
|
1773
|
+
"""
|
|
1774
|
+
if not isinstance(account, dict):
|
|
1775
|
+
raise ValueError("account must be a cash funding row dict")
|
|
1776
|
+
|
|
1777
|
+
account_id = account.get("accountId", account.get("id"))
|
|
1778
|
+
if account_id is None:
|
|
1779
|
+
raise ValueError("account must have an 'id' (or 'accountId') field")
|
|
1780
|
+
|
|
1781
|
+
payload = {k: account[k] for k in RECEIVABLE_SUMMARY_FIELDS if k in account}
|
|
1782
|
+
payload["accountId"] = account_id
|
|
1783
|
+
|
|
1784
|
+
url = f"{self.base_url}/Billing/SyncCashtoEclipse"
|
|
1785
|
+
res = self.api_request(url, requests.post, json=payload)
|
|
1786
|
+
return res.json()
|
|
1787
|
+
|
|
1702
1788
|
# -------------------------------------------------------------------------
|
|
1703
1789
|
# Bill Management
|
|
1704
1790
|
# -------------------------------------------------------------------------
|
|
@@ -2284,30 +2370,71 @@ class EclipseBase(BaseAPI):
|
|
|
2284
2370
|
res = self.api_request(f"{self.base_url}/account/accounts/simple")
|
|
2285
2371
|
return res.json()
|
|
2286
2372
|
|
|
2287
|
-
def get_internal_account_id(self, search_param):
|
|
2373
|
+
def get_internal_account_id(self, search_param, fuzzy=False):
|
|
2288
2374
|
"""Get internal Eclipse account ID from a search parameter.
|
|
2289
2375
|
|
|
2290
|
-
Searches across id, accountName, accountNumber, and portfolioName
|
|
2291
|
-
|
|
2376
|
+
Searches across id, accountName, accountNumber, and portfolioName,
|
|
2377
|
+
then resolves in tiers:
|
|
2378
|
+
|
|
2379
|
+
1. **Exact match:** a result whose internal ``id`` or ``accountNumber``
|
|
2380
|
+
equals ``search_param`` is returned immediately. If an exact-id and
|
|
2381
|
+
an exact-account-number match point at *different* accounts, raises
|
|
2382
|
+
``AmbiguousAccountError`` rather than guessing.
|
|
2383
|
+
2. A single remaining candidate is returned.
|
|
2384
|
+
3. Multiple candidates raise ``AmbiguousAccountError`` listing them,
|
|
2385
|
+
unless ``fuzzy=True``, which returns the first match (the pre-2.28
|
|
2386
|
+
behavior).
|
|
2387
|
+
|
|
2388
|
+
Best use is to pass a full custodian account number. Callers that
|
|
2389
|
+
already hold the internal id should pass it via the
|
|
2390
|
+
``internal_account_id=`` keyword on scoped methods instead of
|
|
2391
|
+
resolving here. For deliberate partial-number + name resolution use
|
|
2392
|
+
:meth:`search_accounts_number_and_name`.
|
|
2292
2393
|
|
|
2293
2394
|
Args:
|
|
2294
2395
|
search_param: Account number, name, or ID to search for
|
|
2396
|
+
fuzzy: When True, silently return the first match when multiple
|
|
2397
|
+
candidates remain (default False)
|
|
2295
2398
|
|
|
2296
2399
|
Returns:
|
|
2297
2400
|
int: The internal Eclipse account ID
|
|
2298
2401
|
|
|
2299
2402
|
Raises:
|
|
2300
2403
|
NotFoundError: If no matching account is found
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
Returns the first matching result, which may not be expected
|
|
2304
|
-
if multiple accounts match the search parameter.
|
|
2404
|
+
AmbiguousAccountError: If multiple accounts match and no exact
|
|
2405
|
+
match singles one out (and ``fuzzy`` is False)
|
|
2305
2406
|
"""
|
|
2306
2407
|
res = self.search_accounts(search_param)
|
|
2307
2408
|
logging.debug("search_accounts result: %s", res)
|
|
2308
2409
|
if not res:
|
|
2309
2410
|
raise NotFoundError(f"No account found for search: {search_param}")
|
|
2310
|
-
|
|
2411
|
+
|
|
2412
|
+
def _candidates(accounts):
|
|
2413
|
+
return [{k: a.get(k) for k in ("id", "name", "accountNumber")} for a in accounts]
|
|
2414
|
+
|
|
2415
|
+
search_str = str(search_param)
|
|
2416
|
+
id_exact = [a for a in res if str(a.get("id")) == search_str]
|
|
2417
|
+
number_exact = [a for a in res if a.get("accountNumber") == search_str]
|
|
2418
|
+
exact = id_exact + [a for a in number_exact if a not in id_exact]
|
|
2419
|
+
if len(exact) == 1:
|
|
2420
|
+
return exact[0]["id"]
|
|
2421
|
+
if len(exact) > 1:
|
|
2422
|
+
raise AmbiguousAccountError(
|
|
2423
|
+
f"Search '{search_param}' exactly matches both an internal id and "
|
|
2424
|
+
f"other account numbers; pass internal_account_id= or a full "
|
|
2425
|
+
f"account number. Candidates: {_candidates(exact)}"
|
|
2426
|
+
)
|
|
2427
|
+
|
|
2428
|
+
if len(res) == 1:
|
|
2429
|
+
return res[0]["id"]
|
|
2430
|
+
if fuzzy:
|
|
2431
|
+
return res[0]["id"]
|
|
2432
|
+
raise AmbiguousAccountError(
|
|
2433
|
+
f"Search '{search_param}' matched {len(res)} accounts with no exact "
|
|
2434
|
+
f"id/accountNumber match. Pass an exact identifier, use "
|
|
2435
|
+
f"search_accounts_number_and_name(), or pass fuzzy=True to accept "
|
|
2436
|
+
f"the first match. Candidates: {_candidates(res)}"
|
|
2437
|
+
)
|
|
2311
2438
|
|
|
2312
2439
|
def search_accounts(self, search_param):
|
|
2313
2440
|
"""Search for accounts by various criteria.
|
|
@@ -2403,7 +2530,7 @@ class EclipseV1(EclipseBase):
|
|
|
2403
2530
|
res = self.api_request(f"{self.base_url}/admin/authorization/user")
|
|
2404
2531
|
return res.json()["userLoginId"]
|
|
2405
2532
|
|
|
2406
|
-
def get_set_asides(self, account_id, active_only=False):
|
|
2533
|
+
def get_set_asides(self, account_id=None, active_only=False, *, internal_account_id=None):
|
|
2407
2534
|
"""Get set-aside cash settings for a specific account (v1 surface).
|
|
2408
2535
|
|
|
2409
2536
|
Returns the raw v1 records from ``GET /account/accounts/{id}/asidecash``.
|
|
@@ -2415,11 +2542,25 @@ class EclipseV1(EclipseBase):
|
|
|
2415
2542
|
account_id: Account ID, number, or name (resolved via search).
|
|
2416
2543
|
active_only: When True, keep only records where ``isActive`` is truthy.
|
|
2417
2544
|
Defaults to False (includes expired/inactive).
|
|
2545
|
+
internal_account_id: Eclipse internal account id, used verbatim with
|
|
2546
|
+
no search resolution — the deterministic path for callers that
|
|
2547
|
+
already hold the id. Mutually exclusive with ``account_id``.
|
|
2418
2548
|
|
|
2419
2549
|
Returns:
|
|
2420
2550
|
list: Raw v1 set-aside records for the account.
|
|
2421
|
-
|
|
2422
|
-
|
|
2551
|
+
|
|
2552
|
+
Raises:
|
|
2553
|
+
ValueError: If both or neither of ``account_id`` /
|
|
2554
|
+
``internal_account_id`` are given.
|
|
2555
|
+
"""
|
|
2556
|
+
if account_id is not None and internal_account_id is not None:
|
|
2557
|
+
raise ValueError("pass account_id (search) or internal_account_id, not both")
|
|
2558
|
+
if internal_account_id is not None:
|
|
2559
|
+
internal_id = int(internal_account_id)
|
|
2560
|
+
elif account_id is not None:
|
|
2561
|
+
internal_id = self.get_internal_account_id(account_id)
|
|
2562
|
+
else:
|
|
2563
|
+
raise ValueError("account_id or internal_account_id is required")
|
|
2423
2564
|
res = self.api_request(f"{self.base_url}/account/accounts/{internal_id}/asidecash")
|
|
2424
2565
|
records = res.json()
|
|
2425
2566
|
if active_only:
|
|
@@ -2428,8 +2569,8 @@ class EclipseV1(EclipseBase):
|
|
|
2428
2569
|
|
|
2429
2570
|
def create_set_aside(
|
|
2430
2571
|
self,
|
|
2431
|
-
account_number,
|
|
2432
|
-
amount,
|
|
2572
|
+
account_number=None,
|
|
2573
|
+
amount=None,
|
|
2433
2574
|
min_amount=0.0,
|
|
2434
2575
|
max_amount=0.0,
|
|
2435
2576
|
description=None,
|
|
@@ -2442,11 +2583,14 @@ class EclipseV1(EclipseBase):
|
|
|
2442
2583
|
deplete_over_time=False,
|
|
2443
2584
|
percent_calc_type=0,
|
|
2444
2585
|
sync=True,
|
|
2586
|
+
*,
|
|
2587
|
+
internal_account_id=None,
|
|
2445
2588
|
):
|
|
2446
2589
|
"""Create a set-aside cash reservation for an account.
|
|
2447
2590
|
|
|
2448
2591
|
Args:
|
|
2449
|
-
account_number: Full custodial account number
|
|
2592
|
+
account_number: Full custodial account number (resolved via search).
|
|
2593
|
+
Mutually exclusive with ``internal_account_id``.
|
|
2450
2594
|
amount: Cash amount to set aside
|
|
2451
2595
|
min_amount: Minimum cash amount (default 0.0)
|
|
2452
2596
|
max_amount: Maximum cash amount (default 0.0)
|
|
@@ -2463,11 +2607,27 @@ class EclipseV1(EclipseBase):
|
|
|
2463
2607
|
percent_calc_type: 0='Use Default/Managed Value', 1='Use Total Value',
|
|
2464
2608
|
2='Use Excluded Value' (default 0)
|
|
2465
2609
|
sync: Wait for analytics to complete (default True)
|
|
2610
|
+
internal_account_id: Eclipse internal account id, used verbatim with
|
|
2611
|
+
no search resolution — the deterministic path for callers that
|
|
2612
|
+
already hold the id. Mutually exclusive with ``account_number``.
|
|
2466
2613
|
|
|
2467
2614
|
Returns:
|
|
2468
2615
|
dict: Created set-aside details
|
|
2469
|
-
|
|
2470
|
-
|
|
2616
|
+
|
|
2617
|
+
Raises:
|
|
2618
|
+
ValueError: If both or neither of ``account_number`` /
|
|
2619
|
+
``internal_account_id`` are given, or ``amount`` is missing.
|
|
2620
|
+
"""
|
|
2621
|
+
if account_number is not None and internal_account_id is not None:
|
|
2622
|
+
raise ValueError("pass account_number (search) or internal_account_id, not both")
|
|
2623
|
+
if amount is None:
|
|
2624
|
+
raise ValueError("amount is required")
|
|
2625
|
+
if internal_account_id is not None:
|
|
2626
|
+
account_id = int(internal_account_id)
|
|
2627
|
+
elif account_number is not None:
|
|
2628
|
+
account_id = self.get_internal_account_id(account_number)
|
|
2629
|
+
else:
|
|
2630
|
+
raise ValueError("account_number or internal_account_id is required")
|
|
2471
2631
|
|
|
2472
2632
|
cash_type_map = {
|
|
2473
2633
|
# end point account/accounts/asideCashAmountType
|
|
@@ -2969,6 +3129,13 @@ class EclipseV1(EclipseBase):
|
|
|
2969
3129
|
:meth:`EclipseV2.create_trades` handles buys *and* sells and honours
|
|
2970
3130
|
share count and dollar amount exactly.
|
|
2971
3131
|
|
|
3132
|
+
Orion support's answer to the sell-500 case (2026-08-03) was to use
|
|
3133
|
+
the **v2** wrapper body (``application`` / ``trades[]`` / ``action`` /
|
|
3134
|
+
``tradeShares``). That body is not accepted here -- posting it to this
|
|
3135
|
+
v1 endpoint returns ``422 "Invalid trade order type id"`` for buys and
|
|
3136
|
+
sells alike -- so it is a redirect to the v2 surface, not a fix for
|
|
3137
|
+
this one. The v1 sell 500 remains unexplained upstream.
|
|
3138
|
+
|
|
2972
3139
|
The generic per-trade creator behind Eclipse's Quick Trade / journal flows,
|
|
2973
3140
|
as opposed to the ``/tradetool/`` generators (:meth:`cash_needs_trade`,
|
|
2974
3141
|
:meth:`rebalance_trade`, ...) which operate on whole portfolios.
|
|
@@ -6561,7 +6728,7 @@ class EclipseV2(EclipseBase):
|
|
|
6561
6728
|
"end_date": end_date,
|
|
6562
6729
|
}
|
|
6563
6730
|
|
|
6564
|
-
def get_set_asides(self, account_id=None, active_only=False):
|
|
6731
|
+
def get_set_asides(self, account_id=None, active_only=False, *, internal_account_id=None):
|
|
6565
6732
|
"""Get set-aside cash reservations, including the Eclipse set-aside id.
|
|
6566
6733
|
|
|
6567
6734
|
Uses the v2 batch endpoint, which accepts a list of internal account IDs
|
|
@@ -6573,15 +6740,27 @@ class EclipseV2(EclipseBase):
|
|
|
6573
6740
|
|
|
6574
6741
|
Args:
|
|
6575
6742
|
account_id: Account ID, number, or name to restrict to a single
|
|
6576
|
-
account
|
|
6577
|
-
|
|
6743
|
+
account (resolved via search). When neither this nor
|
|
6744
|
+
``internal_account_id`` is given, returns set-asides firm-wide
|
|
6745
|
+
by issuing one batch POST over all accounts.
|
|
6578
6746
|
active_only: When True, return only currently-active set-asides.
|
|
6579
6747
|
Defaults to False (includes expired/inactive).
|
|
6748
|
+
internal_account_id: Eclipse internal account id, used verbatim with
|
|
6749
|
+
no search resolution — the deterministic path for callers that
|
|
6750
|
+
already hold the id. Mutually exclusive with ``account_id``.
|
|
6580
6751
|
|
|
6581
6752
|
Returns:
|
|
6582
6753
|
list: Augmented set-aside records
|
|
6583
|
-
|
|
6584
|
-
|
|
6754
|
+
|
|
6755
|
+
Raises:
|
|
6756
|
+
ValueError: If both ``account_id`` and ``internal_account_id`` are
|
|
6757
|
+
given.
|
|
6758
|
+
"""
|
|
6759
|
+
if account_id is not None and internal_account_id is not None:
|
|
6760
|
+
raise ValueError("pass account_id (search) or internal_account_id, not both")
|
|
6761
|
+
if internal_account_id is not None:
|
|
6762
|
+
account_ids = [int(internal_account_id)]
|
|
6763
|
+
elif account_id is not None:
|
|
6585
6764
|
account_ids = [self.get_internal_account_id(account_id)]
|
|
6586
6765
|
else:
|
|
6587
6766
|
account_ids = [a["id"] for a in self.get_all_accounts()]
|
|
@@ -7264,7 +7443,7 @@ class EclipseV2(EclipseBase):
|
|
|
7264
7443
|
def validate_trades(
|
|
7265
7444
|
self,
|
|
7266
7445
|
trades,
|
|
7267
|
-
application=
|
|
7446
|
+
application=TRADING_APPLICATION_QUICK_TRADES,
|
|
7268
7447
|
trade_tool_selection=2,
|
|
7269
7448
|
trade_instance_type=5,
|
|
7270
7449
|
trade_instance_sub_type=11,
|
|
@@ -7291,10 +7470,13 @@ class EclipseV2(EclipseBase):
|
|
|
7291
7470
|
Size each with ``shares`` (share count) or ``amount`` (dollars) --
|
|
7292
7471
|
see :meth:`build_trade` for the full parameter table.
|
|
7293
7472
|
application: ``TradingApplication`` -- see :data:`TRADING_APPLICATIONS`.
|
|
7294
|
-
Defaults to 11 (
|
|
7295
|
-
:meth:`create_trades`.
|
|
7296
|
-
|
|
7297
|
-
|
|
7473
|
+
Defaults to 11 (``QuickTrades``), the only value that creates orders
|
|
7474
|
+
on :meth:`create_trades`. The enum name is also accepted as a string
|
|
7475
|
+
(``"QuickTrades"``) and behaves identically. This endpoint tolerates
|
|
7476
|
+
other values, but they are not equivalent: ``application=1``
|
|
7477
|
+
(CashNeeds) returns ``isValid: False`` with ``tradeAmount: 0`` rather
|
|
7478
|
+
than pricing the trade, so validating under one application and
|
|
7479
|
+
creating under another gives a meaningless pre-flight.
|
|
7298
7480
|
trade_tool_selection: 1=Portfolio, 2=Account, 3=Model, ... (default 2)
|
|
7299
7481
|
trade_instance_type: See :data:`TRADE_INSTANCE_TYPES` (default 5, Quick Trade)
|
|
7300
7482
|
trade_instance_sub_type: See :data:`TRADE_INSTANCE_SUBTYPES`
|
|
@@ -7325,7 +7507,7 @@ class EclipseV2(EclipseBase):
|
|
|
7325
7507
|
def create_trades(
|
|
7326
7508
|
self,
|
|
7327
7509
|
trades,
|
|
7328
|
-
application=
|
|
7510
|
+
application=TRADING_APPLICATION_QUICK_TRADES,
|
|
7329
7511
|
trade_tool_selection=2,
|
|
7330
7512
|
trade_instance_type=5,
|
|
7331
7513
|
trade_instance_sub_type=11,
|
|
@@ -7363,7 +7545,8 @@ class EclipseV2(EclipseBase):
|
|
|
7363
7545
|
Size each with ``shares`` (share count) or ``amount`` (dollars);
|
|
7364
7546
|
see :meth:`build_trade` for the full parameter table.
|
|
7365
7547
|
application: ``TradingApplication`` -- see :data:`TRADING_APPLICATIONS`.
|
|
7366
|
-
**Only 11 (
|
|
7548
|
+
**Only 11 (``QuickTrades``) creates orders**, and it is the default.
|
|
7549
|
+
The enum name is also accepted as a string (``"QuickTrades"``).
|
|
7367
7550
|
Every other value except 14 returns 400 "Trade Application <Name>
|
|
7368
7551
|
is not supported."; 14 returns 200 with an empty ``tradeId`` list
|
|
7369
7552
|
and creates nothing, so it is rejected here rather than allowed to
|
|
@@ -7391,11 +7574,11 @@ class EclipseV2(EclipseBase):
|
|
|
7391
7574
|
>>> e.create_trades([t])["tradeId"]
|
|
7392
7575
|
[72495]
|
|
7393
7576
|
"""
|
|
7394
|
-
if application !=
|
|
7577
|
+
if application != TRADING_APPLICATION_QUICK_TRADES:
|
|
7395
7578
|
name = TRADING_APPLICATIONS.get(application, "unknown")
|
|
7396
7579
|
raise ValueError(
|
|
7397
7580
|
f"application={application} ({name}) does not create trade orders on "
|
|
7398
|
-
f"this endpoint; only {
|
|
7581
|
+
f"this endpoint; only {TRADING_APPLICATION_QUICK_TRADES} (QuickTrades) does. "
|
|
7399
7582
|
"Other values return 400, and 14 returns 200 while creating nothing."
|
|
7400
7583
|
)
|
|
7401
7584
|
for i, t in enumerate(trades or []):
|
|
@@ -11484,13 +11667,19 @@ class Eclipse(EclipseBase):
|
|
|
11484
11667
|
|
|
11485
11668
|
# --- v2-preferred overrides (documented best-of-both choices) ---------------
|
|
11486
11669
|
|
|
11487
|
-
def get_set_asides(self, account_id=None, active_only=False):
|
|
11670
|
+
def get_set_asides(self, account_id=None, active_only=False, *, internal_account_id=None):
|
|
11488
11671
|
"""Set-asides via the v2 batch endpoint (best: firm-wide + set-aside id).
|
|
11489
11672
|
|
|
11490
11673
|
Delegates to :meth:`EclipseV2.get_set_asides`. Use ``self.v1.get_set_asides``
|
|
11491
|
-
for the raw per-account v1 form.
|
|
11674
|
+
for the raw per-account v1 form. Pass ``internal_account_id=`` when you
|
|
11675
|
+
already hold the Eclipse internal id — it is used verbatim, with no
|
|
11676
|
+
search resolution.
|
|
11492
11677
|
"""
|
|
11493
|
-
return self.v2.get_set_asides(
|
|
11678
|
+
return self.v2.get_set_asides(
|
|
11679
|
+
account_id=account_id,
|
|
11680
|
+
active_only=active_only,
|
|
11681
|
+
internal_account_id=internal_account_id,
|
|
11682
|
+
)
|
|
11494
11683
|
|
|
11495
11684
|
|
|
11496
11685
|
class EclipseAPI(Eclipse):
|
|
File without changes
|