orionapi 2.22.0__tar.gz → 2.24.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.24.0"
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
@@ -2406,6 +2406,7 @@ class EclipseV1(EclipseBase):
|
|
|
2406
2406
|
expire_date=None,
|
|
2407
2407
|
expire_trans_tol=0,
|
|
2408
2408
|
expire_trans_type=1,
|
|
2409
|
+
deplete_over_time=False,
|
|
2409
2410
|
percent_calc_type=0,
|
|
2410
2411
|
sync=True,
|
|
2411
2412
|
):
|
|
@@ -2423,6 +2424,9 @@ class EclipseV1(EclipseBase):
|
|
|
2423
2424
|
expire_date: Expiration date (if expire_type='Date')
|
|
2424
2425
|
expire_trans_tol: Transaction tolerance value (default 0)
|
|
2425
2426
|
expire_trans_type: 1='Distribution / Merge Out', 3='Fee' (default 1)
|
|
2427
|
+
deplete_over_time: Maps to the UI "Deplete Over Time" checkbox
|
|
2428
|
+
(``isDepleteOverTime``). Only meaningful when
|
|
2429
|
+
expire_type='Transaction' (default False)
|
|
2426
2430
|
percent_calc_type: 0='Use Default/Managed Value', 1='Use Total Value',
|
|
2427
2431
|
2='Use Excluded Value' (default 0)
|
|
2428
2432
|
sync: Wait for analytics to complete (default True)
|
|
@@ -2487,6 +2491,7 @@ class EclipseV1(EclipseBase):
|
|
|
2487
2491
|
"expirationValue": expire_value,
|
|
2488
2492
|
"toleranceValue": expire_trans_tol,
|
|
2489
2493
|
"transactionTypeId": expire_trans_type,
|
|
2494
|
+
"isDepleteOverTime": bool(deplete_over_time),
|
|
2490
2495
|
"description": description,
|
|
2491
2496
|
"percentCalculationTypeId": percent_calc_type,
|
|
2492
2497
|
},
|
|
@@ -2743,33 +2748,68 @@ class EclipseV1(EclipseBase):
|
|
|
2743
2748
|
self.wait_for_analytics()
|
|
2744
2749
|
|
|
2745
2750
|
def get_orders(self):
|
|
2746
|
-
"""
|
|
2751
|
+
"""Deprecated alias of ``get_trades(is_pending=False)``.
|
|
2752
|
+
|
|
2753
|
+
Both hit the same ``/tradeorder/trades`` endpoint; :meth:`get_trades` is the
|
|
2754
|
+
superset and also exposes the portfolio, block, filter and account filters.
|
|
2755
|
+
Emits a ``DeprecationWarning`` and will be removed in a future major release.
|
|
2747
2756
|
|
|
2748
2757
|
Returns:
|
|
2749
2758
|
list: List of completed trade order dicts
|
|
2750
2759
|
"""
|
|
2751
|
-
|
|
2760
|
+
warnings.warn(
|
|
2761
|
+
"get_orders is deprecated; use get_trades(is_pending=False).",
|
|
2762
|
+
DeprecationWarning,
|
|
2763
|
+
stacklevel=2,
|
|
2764
|
+
)
|
|
2765
|
+
return self.get_trades(is_pending=False)
|
|
2752
2766
|
|
|
2753
2767
|
def get_orders_pending(self):
|
|
2754
|
-
"""
|
|
2768
|
+
"""Deprecated alias of ``get_trades(is_pending=True)``.
|
|
2769
|
+
|
|
2770
|
+
Both hit the same ``/tradeorder/trades`` endpoint; :meth:`get_trades` is the
|
|
2771
|
+
superset and also exposes the portfolio, block, filter and account filters.
|
|
2772
|
+
Emits a ``DeprecationWarning`` and will be removed in a future major release.
|
|
2755
2773
|
|
|
2756
2774
|
Returns:
|
|
2757
2775
|
list: List of pending trade order dicts
|
|
2758
2776
|
"""
|
|
2759
|
-
|
|
2777
|
+
warnings.warn(
|
|
2778
|
+
"get_orders_pending is deprecated; use get_trades(is_pending=True).",
|
|
2779
|
+
DeprecationWarning,
|
|
2780
|
+
stacklevel=2,
|
|
2781
|
+
)
|
|
2782
|
+
return self.get_trades(is_pending=True)
|
|
2760
2783
|
|
|
2761
|
-
def get_trades(
|
|
2762
|
-
|
|
2784
|
+
def get_trades(
|
|
2785
|
+
self,
|
|
2786
|
+
portfolio_id=None,
|
|
2787
|
+
top=None,
|
|
2788
|
+
is_pending=None,
|
|
2789
|
+
block_id=None,
|
|
2790
|
+
filter_id=None,
|
|
2791
|
+
account_ids=None,
|
|
2792
|
+
):
|
|
2793
|
+
"""Get trade orders with optional portfolio / block / filter / pending filters.
|
|
2763
2794
|
|
|
2764
|
-
|
|
2765
|
-
:meth:`get_orders_pending`,
|
|
2766
|
-
|
|
2795
|
+
The canonical accessor for ``GET /tradeorder/trades``. Supersedes the
|
|
2796
|
+
deprecated :meth:`get_orders` / :meth:`get_orders_pending`, which only
|
|
2797
|
+
varied ``is_pending``.
|
|
2767
2798
|
|
|
2768
2799
|
Args:
|
|
2769
2800
|
portfolio_id: Optional portfolio ID filter (maps to ``portfolioId``)
|
|
2770
|
-
top:
|
|
2801
|
+
top: Deprecated and ignored. ``$top`` is not a documented param on this
|
|
2802
|
+
endpoint, and Eclipse silently drops unknown query params rather
|
|
2803
|
+
than erroring — live-verified 2026-07-28: with 10 trades in the
|
|
2804
|
+
tenant, ``$top=3`` still returned all 10. Slice the result instead.
|
|
2771
2805
|
is_pending: Optional bool; when set, filter by pending status
|
|
2772
2806
|
(maps to ``isPending``)
|
|
2807
|
+
block_id: Optional trade block ID filter (maps to ``blockId``)
|
|
2808
|
+
filter_id: Optional trade filter type ID (maps to ``filterId``); see
|
|
2809
|
+
the ``/tradeorder/trades/filterTypes`` endpoint for valid values
|
|
2810
|
+
account_ids: Optional account ID filter (maps to ``accountIds``);
|
|
2811
|
+
accepts a list/tuple of IDs, which is joined to a comma-separated
|
|
2812
|
+
string, or a pre-formatted string
|
|
2773
2813
|
|
|
2774
2814
|
Returns:
|
|
2775
2815
|
list: Trade order dicts
|
|
@@ -2778,12 +2818,189 @@ class EclipseV1(EclipseBase):
|
|
|
2778
2818
|
if portfolio_id is not None:
|
|
2779
2819
|
params["portfolioId"] = portfolio_id
|
|
2780
2820
|
if top is not None:
|
|
2781
|
-
|
|
2821
|
+
warnings.warn(
|
|
2822
|
+
"get_trades(top=...) is ignored by Eclipse: $top is not a supported "
|
|
2823
|
+
"param on /tradeorder/trades and the server silently drops it. "
|
|
2824
|
+
"Slice the returned list instead. This parameter will be removed in "
|
|
2825
|
+
"a future major release.",
|
|
2826
|
+
DeprecationWarning,
|
|
2827
|
+
stacklevel=2,
|
|
2828
|
+
)
|
|
2782
2829
|
if is_pending is not None:
|
|
2783
2830
|
params["isPending"] = str(is_pending).lower()
|
|
2831
|
+
if block_id is not None:
|
|
2832
|
+
params["blockId"] = block_id
|
|
2833
|
+
if filter_id is not None:
|
|
2834
|
+
params["filterId"] = filter_id
|
|
2835
|
+
if account_ids is not None:
|
|
2836
|
+
if isinstance(account_ids, (list, tuple)):
|
|
2837
|
+
account_ids = ",".join(str(a) for a in account_ids)
|
|
2838
|
+
params["accountIds"] = account_ids
|
|
2784
2839
|
res = self.api_request(f"{self.base_url}/tradeorder/trades", params=params)
|
|
2785
2840
|
return res.json()
|
|
2786
2841
|
|
|
2842
|
+
def validate_trade(
|
|
2843
|
+
self,
|
|
2844
|
+
action_id,
|
|
2845
|
+
account_id=None,
|
|
2846
|
+
portfolio_id=None,
|
|
2847
|
+
security_id=None,
|
|
2848
|
+
dollar_amount=None,
|
|
2849
|
+
quantity=None,
|
|
2850
|
+
percentage=None,
|
|
2851
|
+
is_auto_allocate=None,
|
|
2852
|
+
):
|
|
2853
|
+
"""Validate a trade before creating it (``POST /tradeorder/trades/validate``).
|
|
2854
|
+
|
|
2855
|
+
Writes nothing. Use this as the pre-flight check for :meth:`create_trade`,
|
|
2856
|
+
which has no preview / view-only mode of its own.
|
|
2857
|
+
|
|
2858
|
+
Args:
|
|
2859
|
+
action_id: 1=Buy, 2=Sell, 3=Journal In, 4=Journal Out
|
|
2860
|
+
account_id: Optional account ID
|
|
2861
|
+
portfolio_id: Optional portfolio ID
|
|
2862
|
+
security_id: Optional security ID
|
|
2863
|
+
dollar_amount: Optional dollar amount to buy/sell
|
|
2864
|
+
quantity: Optional number of shares to buy/sell
|
|
2865
|
+
percentage: Optional percent of the position to buy/sell
|
|
2866
|
+
is_auto_allocate: Optional bool (maps to ``isAutoAllocate``)
|
|
2867
|
+
|
|
2868
|
+
Returns:
|
|
2869
|
+
dict: ``message``, ``tradeAmount``, ``cashValuePostTrade`` and a
|
|
2870
|
+
``warningMessage`` list (e.g. warnings about overspending cash)
|
|
2871
|
+
"""
|
|
2872
|
+
payload = {
|
|
2873
|
+
"actionId": action_id,
|
|
2874
|
+
"accountId": account_id,
|
|
2875
|
+
"portfolioId": portfolio_id,
|
|
2876
|
+
"securityId": security_id,
|
|
2877
|
+
"dollarAmount": dollar_amount,
|
|
2878
|
+
"quantity": quantity,
|
|
2879
|
+
"percentage": percentage,
|
|
2880
|
+
"isAutoAllocate": is_auto_allocate,
|
|
2881
|
+
}
|
|
2882
|
+
payload = {k: v for k, v in payload.items() if v is not None}
|
|
2883
|
+
|
|
2884
|
+
res = self.api_request(
|
|
2885
|
+
f"{self.base_url}/tradeorder/trades/validate", requests.post, json=payload
|
|
2886
|
+
)
|
|
2887
|
+
return res.json()
|
|
2888
|
+
|
|
2889
|
+
def create_trade(
|
|
2890
|
+
self,
|
|
2891
|
+
action_id,
|
|
2892
|
+
trade_tool_selection,
|
|
2893
|
+
trade_instance_type,
|
|
2894
|
+
trade_instance_sub_type,
|
|
2895
|
+
account_id=None,
|
|
2896
|
+
portfolio_id=None,
|
|
2897
|
+
security_id=None,
|
|
2898
|
+
dollar_amount=None,
|
|
2899
|
+
quantity=None,
|
|
2900
|
+
percentage=None,
|
|
2901
|
+
sync=True,
|
|
2902
|
+
):
|
|
2903
|
+
"""Generate trade orders (``POST /tradeorder/trades``).
|
|
2904
|
+
|
|
2905
|
+
The generic per-trade creator behind Eclipse's Quick Trade / journal flows,
|
|
2906
|
+
as opposed to the ``/tradetool/`` generators (:meth:`cash_needs_trade`,
|
|
2907
|
+
:meth:`rebalance_trade`, ...) which operate on whole portfolios.
|
|
2908
|
+
|
|
2909
|
+
.. warning::
|
|
2910
|
+
This endpoint has **no view-only mode** — it always writes. Call
|
|
2911
|
+
:meth:`validate_trade` first to preview the trade amount, the resulting
|
|
2912
|
+
cash balance and any warnings.
|
|
2913
|
+
|
|
2914
|
+
Trades are always created as pending orders: the wrapper hardcodes
|
|
2915
|
+
``isSendImmediately: false`` and deliberately does not expose it, so a
|
|
2916
|
+
single call can never both create and execute a trade. Review and
|
|
2917
|
+
execute the resulting orders in Eclipse.
|
|
2918
|
+
|
|
2919
|
+
Args:
|
|
2920
|
+
action_id: 1=Buy, 2=Sell, 3=Journal In, 4=Journal Out. (The Eclipse
|
|
2921
|
+
docs list both journal directions as ``3``; ``4`` is accepted on
|
|
2922
|
+
the assumption that Journal Out is ``4``.)
|
|
2923
|
+
trade_tool_selection: 1=Portfolio, 2=Account, 3=Model,
|
|
2924
|
+
4=Account Trade Group, 5=Sleeve Portfolio, 6=Excel Import,
|
|
2925
|
+
7=Portfolio Trade Group, 8=Security Import, 9=Individual Sleeve,
|
|
2926
|
+
10=Tactical Tool
|
|
2927
|
+
trade_instance_type: Trade instance type ID; see
|
|
2928
|
+
:data:`TRADE_INSTANCE_TYPES`
|
|
2929
|
+
trade_instance_sub_type: Trade instance sub-type ID; see
|
|
2930
|
+
:data:`TRADE_INSTANCE_SUBTYPES`
|
|
2931
|
+
account_id: Account ID (required unless ``portfolio_id`` is given)
|
|
2932
|
+
portfolio_id: Portfolio ID (required unless ``account_id`` is given)
|
|
2933
|
+
security_id: Security ID; required for buys and sells
|
|
2934
|
+
dollar_amount: Dollar amount to buy/sell
|
|
2935
|
+
quantity: Number of shares to buy/sell
|
|
2936
|
+
percentage: Percent of the position to buy/sell
|
|
2937
|
+
sync: Wait for analytics to complete (default True)
|
|
2938
|
+
|
|
2939
|
+
Returns:
|
|
2940
|
+
dict: Either ``{"message": ...}`` or ``{"issues": [...],
|
|
2941
|
+
"success": [...], "instanceId": ...}``
|
|
2942
|
+
|
|
2943
|
+
Raises:
|
|
2944
|
+
ValueError: If the enum values are unknown, option trading is
|
|
2945
|
+
requested (unsupported by Eclipse), neither an account nor a
|
|
2946
|
+
portfolio is given, or a buy/sell does not specify exactly one of
|
|
2947
|
+
``dollar_amount`` / ``quantity`` / ``percentage``.
|
|
2948
|
+
"""
|
|
2949
|
+
if action_id not in (1, 2, 3, 4):
|
|
2950
|
+
raise ValueError(
|
|
2951
|
+
"action_id must be 1 (Buy), 2 (Sell), 3 (Journal In) or 4 (Journal Out)"
|
|
2952
|
+
)
|
|
2953
|
+
if trade_tool_selection not in range(1, 11):
|
|
2954
|
+
raise ValueError("trade_tool_selection must be an integer between 1 and 10")
|
|
2955
|
+
if trade_instance_type not in TRADE_INSTANCE_TYPES:
|
|
2956
|
+
raise ValueError(
|
|
2957
|
+
f"trade_instance_type must be one of {sorted(TRADE_INSTANCE_TYPES)}, "
|
|
2958
|
+
f"got {trade_instance_type!r}"
|
|
2959
|
+
)
|
|
2960
|
+
if trade_instance_sub_type not in TRADE_INSTANCE_SUBTYPES:
|
|
2961
|
+
raise ValueError(
|
|
2962
|
+
f"trade_instance_sub_type must be one of {sorted(TRADE_INSTANCE_SUBTYPES)}, "
|
|
2963
|
+
f"got {trade_instance_sub_type!r}"
|
|
2964
|
+
)
|
|
2965
|
+
# Eclipse documents option trading as "not supported" on this endpoint.
|
|
2966
|
+
if trade_instance_type == 4 or trade_instance_sub_type == 9:
|
|
2967
|
+
raise ValueError("Option Trading is not supported by the /tradeorder/trades endpoint")
|
|
2968
|
+
if account_id is None and portfolio_id is None:
|
|
2969
|
+
raise ValueError("at least one of account_id or portfolio_id is required")
|
|
2970
|
+
|
|
2971
|
+
is_buy_or_sell = action_id in (1, 2)
|
|
2972
|
+
if is_buy_or_sell:
|
|
2973
|
+
if security_id is None:
|
|
2974
|
+
raise ValueError("security_id is required for buys and sells")
|
|
2975
|
+
amounts = [a for a in (dollar_amount, quantity, percentage) if a]
|
|
2976
|
+
if len(amounts) != 1:
|
|
2977
|
+
raise ValueError(
|
|
2978
|
+
"exactly one of dollar_amount, quantity or percentage must be set "
|
|
2979
|
+
"for buys and sells"
|
|
2980
|
+
)
|
|
2981
|
+
|
|
2982
|
+
# Buys/sells send 0 for the unused amount fields; journals send null.
|
|
2983
|
+
unset = 0 if is_buy_or_sell else None
|
|
2984
|
+
payload = {
|
|
2985
|
+
"accountId": account_id,
|
|
2986
|
+
"portfolioId": portfolio_id,
|
|
2987
|
+
"actionId": action_id,
|
|
2988
|
+
"securityId": security_id,
|
|
2989
|
+
"dollarAmount": dollar_amount if dollar_amount is not None else unset,
|
|
2990
|
+
"quantity": quantity if quantity is not None else unset,
|
|
2991
|
+
"percentage": percentage if percentage is not None else unset,
|
|
2992
|
+
# Never expose this: creating and executing a trade must stay separate.
|
|
2993
|
+
"isSendImmediately": False,
|
|
2994
|
+
"tradeToolSelection": trade_tool_selection,
|
|
2995
|
+
"tradeInstanceType": trade_instance_type,
|
|
2996
|
+
"tradeInstanceSubType": trade_instance_sub_type,
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2999
|
+
res = self.api_request(f"{self.base_url}/tradeorder/trades", requests.post, json=payload)
|
|
3000
|
+
result = res.json()
|
|
3001
|
+
self._maybe_wait_for_analytics(sync)
|
|
3002
|
+
return result
|
|
3003
|
+
|
|
2787
3004
|
def cash_needs_trade(
|
|
2788
3005
|
self,
|
|
2789
3006
|
portfolio_ids,
|
|
@@ -5179,7 +5396,8 @@ class EclipseV1(EclipseBase):
|
|
|
5179
5396
|
Args:
|
|
5180
5397
|
account_id: Internal account ID
|
|
5181
5398
|
aside_cash_id: Set-aside-cash ID
|
|
5182
|
-
payload: Set-aside DTO (request body)
|
|
5399
|
+
payload: Set-aside DTO (request body). May include ``isDepleteOverTime``
|
|
5400
|
+
(bool), the API equivalent of the UI "Deplete Over Time" checkbox.
|
|
5183
5401
|
"""
|
|
5184
5402
|
return self.api_request(
|
|
5185
5403
|
f"{self.base_url}/account/accounts/{account_id}/asidecash/{aside_cash_id}",
|
|
@@ -5744,7 +5962,8 @@ class EclipseV1(EclipseBase):
|
|
|
5744
5962
|
|
|
5745
5963
|
Args:
|
|
5746
5964
|
portfolio_id: Portfolio ID
|
|
5747
|
-
payload: Set-aside DTO (request body)
|
|
5965
|
+
payload: Set-aside DTO (request body). May include ``isDepleteOverTime``
|
|
5966
|
+
(bool), the API equivalent of the UI "Deplete Over Time" checkbox.
|
|
5748
5967
|
"""
|
|
5749
5968
|
return self.api_request(
|
|
5750
5969
|
f"{self.base_url}/portfolio/portfolios/{portfolio_id}/asideCash",
|
|
File without changes
|