monaco.api.margin_accounts
Source: protos/api/margin_accounts.proto
Use MarginAccountsService for parent margin account state, risk bucket collateral movement, and pre-trade risk checks.
Notes
- Margin account RPCs are authenticated.
- Parent margin account RPCs operate on the authenticated user’s parent account.
- Risk bucket RPCs resolve the target isolated bucket from request context such as trading pair and optional strategy key.
SimulateRiskBucketOrderRiskRequest.selected_trading_pair_idsis deprecated and ignored in CROSS mode, the contractTransferCollateralToRiskBucketRequestalready adopted for its own field. Cross scope is derived from trading — a pair joins the cross risk bucket when a cross order on it succeeds and, once its positions close, stays listed until a later successful cross order on another pair reconciles the bucket — and the preview never priced anything from the list, so requiring it only producedINVALID_ARGUMENTs. A CROSS preview with an empty list, one omittingtrading_pair_id, and one omitting a pair with an open cross position now all succeed, with unchanged figures. The field stays on the wire so pre-deprecation clients keep working; sending a value logs a server-side deprecation warning and has no other effect, and it is still rejected for ISOLATED (selectedTradingPairIds is not supported for ISOLATED risk buckets).SimulateOrderRiskResponse.selected_trading_pair_idsnow reports the DERIVED scope the preview ran against — the active cross bucket’s recorded pairs, every pair with an open position in it, and the previewed pair — never the caller’s list. The generated gRPC struct carries#[deprecated], so build the request with..Default::default()rather than naming the field, which trips rustc’sdeprecatedlint under-D warnings.TransferCollateralFromMarginAccountRequestaccepts an optionalmargin_mode(ISOLATEDorCROSS); setCROSSto release the account’s cross risk bucket, which has no trading pair and cannot be named bytrading_pair_id. It is mutually exclusive withtrading_pair_id, and released collateral returns to the parent margin account.MarginAccountSummarycarriessubaccount_key(defaultfor the default margin account) andmargin_account_state(ACTIVEorCLOSED) on every row, andrisk_bucket_state(NORMAL,PENDING_LIQUIDATION,LIQUIDATING,BAD_DEBT,CLOSED) on risk-bucket rows only.ListMarginAccountsRequest.statefilters onrisk_bucket_state, so any filter excludes margin account rows, which have no state.CreateSubAccountopens a margin sub-account keyed bysubaccount_key: up to 64 letters, digits,_,-,.or:; keys starting withcopy:are reserved anddefaultnames the default margin account. The default margin account must already exist. Re-creating an open key is idempotent; re-creating a closed key re-opens the same account. Open sub-accounts are capped per owner by weighted 14-day volume tier (10 at the first tier, rising with the fee-tier floors to 50) or an admin override; copy-trading sub-accounts do not count. ReturnsINVALID_ARGUMENTfor a malformed, reserved ordefaultkey, a missing default margin account, or a create past the cap;PERMISSION_DENIEDfor delegated-agent sessions;RESOURCE_EXHAUSTED(withRetryInfo) past the per-user movement budget;UNAVAILABLEwhen no matching engine connection is configured or the new account has not been projected yet; andINTERNALwhen the call to the matching engine fails in transit.CloseSubAccountcloses a flat sub-account (no position, resting order, conditional order or TWAP) in one call: its flat, solvent risk buckets close and all of its remaining collateral moves to the default margin account.CloseSubAccountResponsenamesmargin_account_id,default_margin_account_idand theamountmoved. ReturnsINVALID_ARGUMENTfor the default margin account, a copy-trading sub-account (closed by stopping its follow), an already-closed sub-account, a sub-account that is not flat, or one with a risk bucket in liquidation, in bad debt, or insolvent — nothing moves;NOT_FOUNDfor an account that is not the caller’s;PERMISSION_DENIEDfor delegated-agent sessions;RESOURCE_EXHAUSTEDpast the movement budget;UNAVAILABLEwhen no matching engine connection is configured;INTERNALwhen the call to the matching engine fails in transit.GetMarginAccountPnlreturns one of the caller’s margin accounts’ ownrealized_pnl(settled on the account plus still held in its open risk buckets) andunrealized_pnl(open positions at the latest risk marks); the caller’s accounts sum to the owner-wide figure. ReturnsINVALID_ARGUMENTfor a malformed id,NOT_FOUNDfor an account that is not the caller’s, andRESOURCE_EXHAUSTEDpast the read budget.TransferCollateralmoves collateral betweenfromandtoCollateralTransferEndpoints, each naming exactly one ofwalletandmargin_account_id. Served moves: wallet to the default margin account and back, and margin account to margin account. An endpoint carryingrisk_bucket_idis refused withINVALID_ARGUMENT— fund risk buckets withTransferCollateralToRiskBucket. AlsoINVALID_ARGUMENTfor wallet to wallet, a wallet transfer naming a sub-account, the same account on both sides, or a closed account;NOT_FOUNDfor an account that is not the caller’s;PERMISSION_DENIEDfor delegated-agent sessions;RESOURCE_EXHAUSTEDpast the movement budget.TransferCollateralToSubAccountmovesamountfrom the caller’s default margin account to the sub-accountmargin_account_id;TransferCollateralFromSubAccountmoves it back. Each is the same one-step account-to-account move asTransferCollateral. ReturnsINVALID_ARGUMENTwhenmargin_account_idis the default margin account (use the parent-margin-account RPCs), the sub-account is closed, or the amount exceeds the source’s free collateral;NOT_FOUNDfor an account that is not the caller’s;PERMISSION_DENIEDfor delegated-agent sessions;RESOURCE_EXHAUSTEDpast the movement budget.TransferCollateralToRiskBucketRequest.margin_account_idandSimulateRiskBucketOrderRiskRequest.margin_account_idselect the margin account: omit it for the default margin account, or name one of the caller’s open sub-accounts to fund or preview that sub-account’s own risk buckets. A closed sub-account or a copy-trading sub-account isINVALID_ARGUMENT; another user’s account isNOT_FOUND.ListMarginAccounts,GetMarginAccountMovementsandGetParentMarginAccountMovementsare cursor-paginated: send an emptypage_tokento start, then each response’snext_page_tokenuntil it comes back empty;page_sizeis 1 to 1000. There is nopagefield: a stub generated from an older proto that still sets it is not rejected (protobuf discards the unknown field) and reads the first page on every call, so regenerate stubs and walk the token.

