Development Guides

Standard Portfolio Rebalance

Overview

The Rebalancer aligns a portfolio with the model it tracks. It identifies securities that are underweight or overweight relative to their model targets and generates buy and sell trade orders to bring the portfolio back into line.

This guide covers Standard rebalances of non-sleeved (Normal) portfolios. For other variants, see:

  • Sleeve Portfolio Rebalances — sleeved portfolios
  • Focused (Tactical) Rebalances — constraining a run to a subset of symbols

1. Endpoint

MethodPOST
URLhttps://www.orioneclipse.com/v1/tradetool/rebalancer/action/generatetrade

Headers

HeaderValue
AuthorizationSession <access_token>
Content-Typeapplication/json

2. Quick Start

To kick off a standard rebalance, you need three things:

  1. A valid session token
  2. The portfolioId of the non-sleeved portfolio you want to rebalance
  3. A POST request with the body below

Copy this template exactly, replace the portfolio id in portfolioIds, and send it. The fields you may want to customize are covered in §3.2 — all others should be sent as shown.

Send the request and you’ll get back a trade instance id and the trades the rebalancer generated. See §4 for the response shape.


3. Request Body

3.1 Required identifiers & metadata

These four fields must always be present.

FieldTypeValueNotes
portfolioIdsint[]e.g. [154694]One or more non-sleeved portfolio IDs. For a single portfolio, send a one-element array.
tradeInstanceTypeint6Portfolio rebalance.
tradeInstanceSubTypeint14Standard portfolio rebalance.
tradeToolSelectionint10From the rebalance tool.

You do not send tradeInstanceId. The backend creates the trade instance and returns its id in the response.

3.2 Fields you may want to customize

FieldTypeRecommendedNotes
useDefaultPreferencebooltrueUse the firm’s saved rebalance preferences. Strongly recommended. When true, allowWashSale, allowShortTermGain, and maxGainAmount are ignored and the firm’s saved values are used instead.
isViewOnlybool | nullnullnull generates committable trades that flow to execution. Set to true only to preview trades without committing them.
rebalanceTypestring | nullnullnull = Standard Rebalance. For focused/tactical runs, see the Focused Rebalance guide.
reasonstring | nullnullOptional free-text reason logged on the trade instance.
minimumTradeAmount{ type, amount }{ “type”: “$”, “amount”: null }Minimum trade amount. amount: null uses the firm’s default. If type: “%”, amount must be ≤ 100.
maxGainAmountdecimal | nullnullCap on the total realized gain produced by this run. null = no override (uses firm default). Only honored when useDefaultPreference: false.
allowWashSalebool | nullnullOverride the firm’s wash-sale rule. null = use the firm’s saved value. Only honored when useDefaultPreference: false.
allowShortTermGainstring | nullnullOverride the firm’s short-term-gain rule. null = use the firm’s saved value. Accepted values: “Allow”, “Full Position Disallow”, “TaxLot Disallow”. Only honored when useDefaultPreference: false.

All other fields in the Quick Start template should be sent exactly as shown.


4. Response

A successful call returns 200 OK.

4.1 Sample response

An empty trades: [] array is success, not failure. It means the portfolio is already in tolerance. Handle this case explicitly in your caller.

4.2 Top-level fields

FieldTypeDescription
tradeInstanceIdlongServer-generated id for this run. Save it — it’s how you’ll find or reconcile the trades downstream.
instanceIdlongSame value as tradeInstanceId. Both are returned for backward compatibility.
isViewOnlyboolEchoes the resolved value. Confirms whether trades were saved as preview or committable.
shouldUseV2PostTradeProcessbooltrue when the run used the current post-trade pipeline.
tradesTrade[]Every trade saved against this instance. For non-sleeved portfolios, contains only BUY and SELL rows.

4.3 Trade object fields (response only)

Each entry in the trades[] array is generated by the rebalancer — none of these fields are set by the caller. The list below covers the fields most external consumers use.

Identity

FieldTypeDescription
tradeIdintUnique id of this trade row.
tradeInstanceIdlongParent trade instance id.
portfolioIdintPortfolio this trade belongs to.
accountIdintAccount this trade belongs to.
securityIdintInternal security id.
symbolstringSecurity symbol (e.g. MSFT).
securityNamestringHuman-readable security name.
securityTypestringEquity, Mutual Fund, Bond, Other.

Action

FieldTypeDescription
actionstringBUY or SELL.
approvalStatusstringCurrent approval state (e.g. Approved).
rebalanceLevelstringAlways Portfolio for this endpoint.
rebalanceLevelIdintAlways 2.
tradeCreatedDateISO datetimeWhen the trade was created.

Quantity & price

FieldTypeDescription
tradeSharesdecimalWhole shares (rounded inline).
pricedecimalPer-share price used.
tradeAmountdecimalTotal dollar value (tradeShares × price).
cashValuePostTradedecimalAccount cash immediately after the trade.
priceDateISO datetimeAs-of date of the price.

Cost basis & gain/loss (sells only)

FieldTypeDescription
costAmountdecimalTotal cost basis.
costPerSharedecimalPer-share cost basis.
tradeGainLossdecimalTotal realized gain or loss.
tradeSTGainLoss / tradeLTGainLossdecimalShort-term / long-term split.

Custodian & fees

FieldTypeDescription
custodianIdintInternal custodian id.
custodianstringCustodian display name.
transactionFeedecimalTransaction fee on this trade.
redemptionFeedecimalRedemption fee on this trade.

Account & tax context

FieldTypeDescription
taxableTypestringTAXABLE, TAXDEF, TAXEXMPT.
billingAccountint (0/1)1 if this is a billing account.

5. Errors

5.1 Error body

The message field (prefixed with [REBAL] : is the canonical signal for what went wrong. Surface it in your logs — don’t rely on the HTTP status alone.

5.2 Status codes

CodeMeaning
200 OKRebalance completed. Includes the case where trades: [] because the portfolio was already in tolerance.
400 Bad RequestRequest validation failed (missing required field, or minimumTradeAmount.type = “%” with amount > 100).
401 / 403Missing, invalid, or unauthorized token.
500 Internal Server ErrorPortfolio, model, or account-level check failed. Read the [REBAL] : message.

5.3 Common failure messages

  • [REBAL] : No Model Assigned to this portfolio.
  • [REBAL] : Portfolio is marked Do Not Trade.
  • [REBAL] : Portfolio analytics are still running.
  • [REBAL] : No Primary Team Assigned to this portfolio.
  • [REBAL] : Invalid Portfolio/Account type sent in request parameters. — typically means you sent a sleeved portfolio to this endpoint. Sleeved portfolios use the same URL but must meet the sleeved requirements;

6. Important Reminders

  • Save the tradeInstanceId from the response. It’s how you’ll look up or reconcile the generated trades later. You cannot supply it in the request — the backend always creates a new one.
  • Empty trades: [] is success. It means the portfolio was already within tolerance. Handle it explicitly.
  • Run post-import analysis first if the portfolio was just imported. If analytics are pending, this endpoint returns 500 with a message saying analysis is required or running. Wait for post-import analysis to complete, then retry.
  • This endpoint does not execute trades. It only generates and saves them. Execution to a custodian or broker is a separate downstream system.
  • You own idempotency, concurrency, and rate limiting. Every call creates a new trade instance and a new set of trades — the endpoint does not de-duplicate retries or block concurrent runs against the same portfolio.
  • Send a non-sleeved portfolio. The endpoint infers the variant from portfolioIds. A sleeved portfolio here will return 500 with Invalid Portfolio/Account type sent in request parameters.