{
  "format": "siebly-integration-kit/v1",
  "id": "binance-position-manager",
  "title": "Binance Manual Position Manager Integration Kit",
  "lastReviewed": "2026-04-29",
  "package": {
    "ecosystem": "npm",
    "name": "binance",
    "verifiedVersion": "3.5.6",
    "install": "npm install binance@3.5.6",
    "docs": "https://siebly.io/sdk/binance/typescript",
    "repository": "https://github.com/tiagosiebler/binance"
  },
  "sourceVerificationChecklist": [
    "Record the installed binance package version before coding.",
    "Inspect SDK docs, endpoint map, examples, installed TypeScript declarations, and package source for the methods and types below.",
    "Verify the USD-M Algo Orders guide and recipe before coding futures TP/SL conditionals.",
    "Write a source-verification note in the generated README or docs with exact methods, types, and files checked."
  ],
  "canonicalSources": [
    "https://siebly.io/ai/binance-position-manager",
    "https://siebly.io/.well-known/recipes/binance-position-manager.json",
    "https://siebly.io/ai/binance-usdm-algo-orders",
    "https://siebly.io/.well-known/recipes/binance-usdm-algo-orders.json",
    "https://siebly.io/sdk/binance/typescript",
    "https://siebly.io/llms-tasks.txt",
    "https://siebly.io/.well-known/siebly-sdk-catalog.json",
    "https://github.com/tiagosiebler/binance",
    "https://github.com/sieblyio/crypto-api-examples/tree/master/examples/Binance"
  ],
  "sdkSurface": {
    "restClients": [
      "MainClient",
      "USDMClient"
    ],
    "websocketClient": "WebsocketClient",
    "privateStreamHelpers": [
      "subscribeSpotUserDataStream",
      "subscribeUsdFuturesUserDataStream"
    ],
    "websocketEvents": [
      "open",
      "response",
      "formattedMessage",
      "formattedUserDataMessage",
      "reconnecting",
      "reconnected",
      "exception"
    ],
    "shutdown": "closeAll(true) or current documented closeAll variant",
    "spotRest": [
      "getExchangeInfo",
      "getAccountInformation",
      "getOpenOrders",
      "getAllOrders",
      "getAccountTradeList",
      "submitNewOrder",
      "cancelOrder",
      "testNewOrder"
    ],
    "usdmRest": [
      "getExchangeInfo",
      "getPositionsV3",
      "getAllOpenOrders",
      "getOpenAlgoOrders",
      "getAccountTrades",
      "getAllOrders",
      "getAccountInformationV3",
      "getCurrentPositionMode",
      "getMultiAssetsMode",
      "getFuturesSymbolConfig",
      "getNotionalAndLeverageBrackets",
      "submitNewOrder",
      "cancelOrder",
      "testOrder",
      "submitNewAlgoOrder",
      "cancelAlgoOrder"
    ],
    "customClientIdFields": {
      "spotAndUsdmRegular": "newClientOrderId",
      "usdmAlgoConditional": "clientAlgoId"
    }
  },
  "requestFieldMatrix": [
    {
      "mode": "USD-M one-way LONG",
      "hydratedPosition": "positionSide=BOTH and signed positionAmt > 0",
      "managedStrategySide": "LONG",
      "outboundPositionSide": "BOTH",
      "dcaAddSide": "BUY below entry",
      "takeProfitSide": "SELL above entry",
      "stopLossSide": "SELL below entry",
      "algoReduceOnly": "Allowed only for validated quantity-based reduce-only exits when configured; omit when closePosition=true."
    },
    {
      "mode": "USD-M one-way SHORT",
      "hydratedPosition": "positionSide=BOTH and signed positionAmt < 0",
      "managedStrategySide": "SHORT",
      "outboundPositionSide": "BOTH",
      "dcaAddSide": "SELL above entry",
      "takeProfitSide": "BUY below entry",
      "stopLossSide": "BUY above entry",
      "algoReduceOnly": "Allowed only for validated quantity-based reduce-only exits when configured; omit when closePosition=true."
    },
    {
      "mode": "USD-M hedge LONG",
      "hydratedPosition": "positionSide=LONG",
      "managedStrategySide": "LONG",
      "outboundPositionSide": "LONG",
      "dcaAddSide": "BUY below entry",
      "takeProfitSide": "SELL above entry",
      "stopLossSide": "SELL below entry",
      "algoReduceOnly": "Omit reduceOnly from Algo TP/SL conditionals."
    },
    {
      "mode": "USD-M hedge SHORT",
      "hydratedPosition": "positionSide=SHORT",
      "managedStrategySide": "SHORT",
      "outboundPositionSide": "SHORT",
      "dcaAddSide": "SELL above entry",
      "takeProfitSide": "BUY below entry",
      "stopLossSide": "BUY above entry",
      "algoReduceOnly": "Omit reduceOnly from Algo TP/SL conditionals."
    },
    {
      "mode": "close-position stop-market",
      "fields": "type=STOP_MARKET, closePosition=true, triggerPrice, workingType, priceProtect, clientAlgoId, side, positionSide",
      "forbiddenFields": [
        "quantity",
        "reduceOnly"
      ]
    },
    {
      "mode": "quantity-based take-profit",
      "fields": "type=TAKE_PROFIT, quantity, price, triggerPrice, timeInForce=GTC, workingType, priceProtect, clientAlgoId, side, positionSide",
      "oneWayReduceOnly": "May include reduceOnly=true in one-way BOTH only when configured and locally validated.",
      "hedgeReduceOnly": "Omit reduceOnly for hedge-mode LONG or SHORT Algo conditionals."
    }
  ],
  "eventReconciliationPolicy": {
    "sourceOfTruth": "REST startup, reconnect, and unknown-submission hydration are the recovery source of truth; private user-data events are the live update stream.",
    "replacementViews": [
      "positions",
      "regularOpenOrders",
      "algoOpenOrders"
    ],
    "workflowLock": "One per-product workflow lock covers REST reconciliation, buffered user-data replay, planning, and live submission.",
    "activeWorkflowUserData": "Buffer and coalesce user_data_* replans while the workflow lock is held; expected own-order NEW confirmations are info logs.",
    "idleUserData": "Run REST reconciliation before planning, but debounce ACCOUNT_UPDATE-only clusters by 750ms-1500ms per product with a 3000ms max delay to avoid one full hydration per event.",
    "immediateUserDataEvents": "ORDER_TRADE_UPDATE, ALGO_UPDATE, fills, cancels, and rejects reconcile immediately.",
    "skipAlreadyReplayed": "Skip only when bufferedEventCount === 0 and every deferred reason starts with user_data_.",
    "immediateReconciliationTriggers": [
      "startup",
      "reconnect or stale private stream",
      "live rejection",
      "unknown submission state",
      "conflicting REST/history/user-data state"
    ]
  },
  "hydrationRules": [
    "REST open positions, regular open orders, and open Algo orders replace the current product snapshot for the hydrated scope.",
    "Absent app-owned open orders are terminal or stale unless a newer user-data event proves otherwise.",
    "Recent history is metadata and terminal evidence, not the active open-order view.",
    "Current open or provisional app-owned order state wins over older terminal history for the same client ID.",
    "If timestamps, statuses, or identifiers conflict and cannot be resolved deterministically, pause the product and reconcile instead of submitting."
  ],
  "lifecycleRules": [
    "Separate manual-position lifecycle epoch from DCA replacement generation.",
    "A fresh manual position on the same product, symbol, and strategy side receives a new lifecycle epoch.",
    "Restarting the same still-open position preserves its lifecycle epoch.",
    "App-owned order metadata stores product, symbol, exchange positionSide, managed strategy side, lifecycle epoch, role, and DCA generation.",
    "Cleanup stale wrong-side or stale-lifecycle app-owned DCA/TP/SL orders before placing new current-lifecycle orders.",
    "After manual full close or position flip, clean up app-owned DCA as well as TP/SL because DCA orders can reopen exposure."
  ],
  "rejectionCatalog": [
    {
      "code": "-1106",
      "cause": "reduceOnly was sent when the current USD-M Algo field mix does not require it.",
      "localAction": "Omit reduceOnly with closePosition=true and omit reduceOnly for hedge-mode Algo TP/SL conditionals unless current docs require it."
    },
    {
      "code": "-2011",
      "cause": "Cancel targeted an order the exchange no longer has open.",
      "localAction": "If current regular open-order or open-Algo hydration is absent for that app-owned ID, mark terminal/stale and stop retrying forever."
    },
    {
      "code": "-4116",
      "cause": "Duplicate deterministic client ID or replayed submission.",
      "localAction": "Track in-flight IDs, insert accepted responses into local state immediately, and reconcile before any retry."
    },
    {
      "code": "-1111",
      "cause": "Precision or filter validation missing, stale, or using the wrong product filters.",
      "localAction": "Re-read filters, normalize tick/step/notional rules, and block invalid rounded requests locally."
    },
    {
      "code": "-1116",
      "cause": "Invalid order type, such as strategy-language TAKE_PROFIT_LIMIT for current USD-M Algo TP.",
      "localAction": "Verify current package types and use valid Algo type literals such as TAKE_PROFIT."
    }
  ],
  "fixtures": [
    "Clean startup: startup reconcile -> submit DCA/TP/SL -> own-order user-data confirmations deferred -> one deferred reconcile replays all buffered events -> planner intentCount=0 -> already-drained deferrals skipped.",
    "Manual full close: position size is zero and app-owned DCA/TP/SL remain; cleanup app-owned orders only.",
    "Two separate manual positions on same symbol and side: second position gets a new lifecycle epoch and does not inherit stale orders/fills from the first.",
    "One-way short: positionSide=BOTH plus negative positionAmt becomes managed strategy side SHORT while outbound requests still send positionSide=BOTH.",
    "Stale wrong-side cleanup: old short-side app-owned DCA/TP/SL exist, hydration shows long position, cleanup emits before new long placement.",
    "Position flip stale unknown Algo cancel: app-owned close-position Algo is absent from open Algo hydration and -2011 does not retry forever.",
    "Hedge-mode TP/SL: positionSide=LONG or SHORT conditionals omit reduceOnly; one-way BOTH fixture covers configured quantity-based reduceOnly.",
    "Idle ACCOUNT_UPDATE storm: repeated account updates debounce by 750ms-1500ms per product with a 3000ms max delay, without skipping startup, reconnect, order/fill/algo, reject, cancel, or unknown-state hydration.",
    "Filter precision failure: hydrated filters block or round locally before Binance returns -1111.",
    "Duplicate client ID: accepted response inserts provisional local state and clears in-flight ID before stream confirmation."
  ],
  "debouncePolicy": {
    "immediateEvents": [
      "ORDER_TRADE_UPDATE",
      "ALGO_UPDATE",
      "fills",
      "cancels",
      "rejects",
      "startup",
      "reconnect",
      "unknown submission state",
      "conflicting state"
    ],
    "accountUpdateOnly": {
      "debounceMs": {
        "min": 750,
        "preferred": 1000,
        "max": 1500
      },
      "maxDelayMs": 3000,
      "coalesceBy": "product"
    },
    "rationale": "Live feedback showed Binance often emitted account-only clusters within 1-2 seconds; a 1s product-level debounce collapses idle reconciliations without delaying order/fill recovery materially."
  },
  "sourceReferenceNotes": {
    "packageVersion": "binance@3.5.6",
    "localVerification": "These references come from live-agent feedback. Generated projects should verify them against their installed node_modules before coding.",
    "sdkLookupTargets": [
      "FuturesNewAlgoOrderParams",
      "FuturesNewAlgoOrderParams.positionSide",
      "FuturesNewAlgoOrderParams.closePosition",
      "FuturesNewAlgoOrderParams.reduceOnly",
      "USDMClient.submitNewAlgoOrder(params: FuturesNewAlgoOrderParams)"
    ],
    "officialDocsRuntimeRules": [
      "USD-M New Algo Order docs: positionSide must be LONG or SHORT in Hedge Mode.",
      "USD-M New Algo Order docs: reduceOnly cannot be sent in Hedge Mode and cannot be sent with closePosition=true."
    ]
  },
  "expectedLogTimeline": [
    "source_verification_complete with package version and method/type list",
    "startup_reconciliation_started",
    "product_snapshot_replaced with compact counts",
    "position_classified with exchangePositionSide and managedStrategySide",
    "stale_app_owned_cleanup_planned before new placement when needed",
    "planner_finished with intentCount and blockedCount",
    "submission_batch_started under workflow lock",
    "live_submission_accepted with provisionalInserted=true and inFlightClientIds count",
    "replan_deferred_workflow_active level=info for expected user_data_* confirmations",
    "processing_deferred_replans with bufferedEventCount",
    "product_reconciled after replay",
    "planner_finished intentCount=0",
    "deferred_replan_already_replayed skipped=true when buffer is empty",
    "shutdown_summary with counts, readiness, bufferedEventCount, compact positions, compact active app-owned orders"
  ]
}
