@@ -66,7 +66,7 @@ async with AsyncPerpsClient.from_env(demo=True) as perps:
6666| ` margin ` | ` balance() ` , ` risk() ` , ` notional_risk_limit() ` , ` fee_tiers() ` , ` fee_tier_rates() ` , ` api_limits() ` , ` corporate_actions() ` |
6767| ` funding ` | ` rate_estimate() ` , ` historical_rates() ` , ` premium_index() ` , ` history() ` |
6868| ` transfers ` | ` transfer_instance() ` , ` create_subaccount() ` , ` transfer_subaccount() ` |
69- | ` fcm ` | ` create_subtrader(subtrader_suffix=..., require_category_cap=...) ` ; ` risk_controls ` / ` update_risk_controls ` / ` delete_risk_controls ` ; ` update_notional_risk_limit ` / ` delete_notional_risk_limit ` |
69+ | ` fcm ` | ` create_subtrader(subtrader_suffix=..., require_category_cap=...) ` ; ` risk_controls ` / ` update_risk_controls ` / ` delete_risk_controls ` ; ` update_notional_risk_limit ` / ` delete_notional_risk_limit ` ; ` transfer_position(...) ` |
7070
7171` markets.bulk_orderbooks(*, tickers) ` fetches up to 100 margin orderbooks
7272in one call (` GET /margin/markets/orderbooks ` ). ` tickers ` is required
@@ -228,10 +228,11 @@ perps.portfolio.cancel_cross_exit_trigger("BTC-PERP", trig.id)
228228- ** Subaccounts** (since the v3.21.0 spec sync) — ` MarginPosition ` (the
229229 ` portfolio.positions() ` rows) carries a ** required** ` subaccount ` (` int ` )
230230 identifying which subaccount holds the position. ` subaccount_type `
231- (` "cross" ` / ` "isolated" ` / ` "auto_rebalance" ` , or ` None ` when the key is
232- absent) is optional on ` MarginPosition ` , ` MarginSubaccountBalance ` ,
233- ` MarginRiskPosition ` , and ` MarginFundingHistoryEntry ` . The spec marks it
234- required; the SDK keeps it optional so older payloads still parse.
231+ (` "cross" ` / ` "isolated" ` / ` "auto_rebalance" ` / ` "managed_isolated" ` , or
232+ ` None ` when the key is absent) is optional on ` MarginPosition ` ,
233+ ` MarginSubaccountBalance ` , ` MarginRiskPosition ` , and
234+ ` MarginFundingHistoryEntry ` . The spec marks it required; the SDK keeps it
235+ optional so older payloads still parse.
235236- ** Portfolio hedging** (since the v3.23.0 spec sync) — ` MarginPosition ` and
236237 ` MarginRiskPosition ` carry a ** required** ` is_portfolio ` (` bool ` ), ` True ` when
237238 the position is hedged within a portfolio so its margin is computed at the
@@ -318,7 +319,32 @@ REST-only); subscribe with `session.subscribe(channel="corporate_actions")`.
318319Upcoming and recent notices are listed by ` margin.corporate_actions() ` .
319320` subscribe_market_lifecycle() ` yields ` MarginMarketLifecycleV2Message ` for
320321activation and deactivation of every margin market (` event_type ` is
321- ` activated ` or ` deactivated ` ). Ticker filters are not supported on that channel.
322+ ` activated ` or ` deactivated ` ). ` is_deactivated ` is true when trading is
323+ paused because the market is halted or outside its trading hours. Ticker
324+ filters are not supported on that channel.
325+
326+ ## FCM position transfer
327+
328+ FCM members can move a perps position in one market from a customer
329+ subtrader into a subtrader under the FCM's error account. ** Kalshi must
330+ enable this endpoint for your FCM** ; until then the server returns 400.
331+ While transfers are switched off for the exchange, requests return 409.
332+ POST is never retried. ` client_transfer_id ` is a required UUID
333+ idempotency key per source subtrader. Supply ` ticker ` or ` market_id `
334+ (ticker wins if both).
335+
336+ ``` python
337+ resp = perps.fcm.transfer_position(
338+ source_subtrader_id = " user_CUST123" ,
339+ target_subtrader_id = " err_ERR1" ,
340+ ticker = " KXBTCPERP" ,
341+ side = " long" ,
342+ count = " 10" ,
343+ price = " 63000.00" ,
344+ client_transfer_id = " 6d1f0c5a-2b3e-4f7a-9c8d-0e1f2a3b4c5d" ,
345+ )
346+ print (resp.position_transfer_id)
347+ ```
322348
323349## Self-Clearing-Member "Klear" API
324350
0 commit comments