Last active
May 3, 2025 13:23
-
-
Save coccoinomane/efeb6e213e5d34ca66ebdc72b478a215 to your computer and use it in GitHub Desktop.
Binance spot OCO orders via CCXT implicit API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Exchange, Order } from 'ccxt'; | |
/** | |
* Create a spot OCO order using CCXT implicit API for Binance. | |
* | |
* An OCO order (one-cancels-the-other) contains a take profit and a stop loss | |
* order for the same amount. | |
* | |
* @link https://developers.binance.com/docs/binance-spot-api-docs/rest-api/trading-endpoints#new-order-list---oco-trade | |
* | |
* @param {Exchange} exchange - The exchange object | |
* @param {string} symbol - The symbol of the market | |
* @param {'buy' | 'sell'} side - The side of the order | |
* @param {number} amount - The amount of the order | |
* @param {number} takeProfitTriggerPrice - The trigger price of the take profit order | |
* @param {number} stopLossTriggerPrice - The trigger price of the stop loss order | |
* @param {number} [takeProfitLimitPrice] - The limit price of the take profit order | |
* @param {number} [stopLossLimitPrice] - The limit price of the stop loss order | |
* @returns {[Order, Order]} - The two orders created | |
*/ | |
export async function createBinanceOcoOrder( | |
exchange: Exchange, | |
symbol: string, | |
side: 'buy' | 'sell', | |
amount: number, | |
takeProfitTriggerPrice: number, | |
stopLossTriggerPrice: number, | |
takeProfitLimitPrice?: number, | |
stopLossLimitPrice?: number, | |
): Promise<[Order, Order]> { | |
// Fetch market object | |
const markets = await exchange.loadMarkets(); | |
const market = markets[symbol]; | |
if (!market) { | |
throw new Error(`Market ${symbol} not found`); | |
} | |
// Determine parameters to send Binance | |
const args: any = { | |
symbol: market.id, | |
side: side.toUpperCase(), | |
quantity: exchange.amountToPrecision(symbol, amount), | |
}; | |
if (side === 'sell') { | |
// Above order is a take profit order | |
args.aboveType = takeProfitLimitPrice ? 'TAKE_PROFIT_LIMIT' : 'TAKE_PROFIT'; | |
args.aboveStopPrice = exchange.priceToPrecision(symbol, takeProfitTriggerPrice); | |
if (takeProfitLimitPrice) { | |
args.abovePrice = exchange.priceToPrecision(symbol, takeProfitLimitPrice); | |
args.aboveTimeInForce = 'GTC'; | |
} | |
// Below order is a stop loss order | |
args.belowType = stopLossLimitPrice ? 'STOP_LOSS_LIMIT' : 'STOP_LOSS'; | |
args.belowStopPrice = exchange.priceToPrecision(symbol, stopLossTriggerPrice); | |
if (stopLossLimitPrice) { | |
args.belowPrice = exchange.priceToPrecision(symbol, stopLossLimitPrice); | |
args.belowTimeInForce = 'GTC'; | |
} | |
} else { | |
// Above order is a stop loss order | |
args.aboveType = stopLossLimitPrice ? 'STOP_LOSS_LIMIT' : 'STOP_LOSS'; | |
args.aboveStopPrice = exchange.priceToPrecision(symbol, stopLossTriggerPrice); | |
if (stopLossLimitPrice) { | |
args.abovePrice = exchange.priceToPrecision(symbol, stopLossLimitPrice); | |
args.aboveTimeInForce = 'GTC'; | |
} | |
// Below order is a take profit order | |
args.belowType = takeProfitLimitPrice ? 'TAKE_PROFIT_LIMIT' : 'TAKE_PROFIT'; | |
args.belowStopPrice = exchange.priceToPrecision(symbol, takeProfitTriggerPrice); | |
if (takeProfitLimitPrice) { | |
args.belowPrice = exchange.priceToPrecision(symbol, takeProfitLimitPrice); | |
args.belowTimeInForce = 'GTC'; | |
} | |
} | |
// Send the request to Binance | |
const response = await (exchange as any).privatePostOrderListOco(args); | |
// Parse the response into two orders | |
try { | |
const binanceOrders = response.orderReports; | |
return binanceOrders.map((o: any) => exchange.parseOrder(o)); | |
} catch (error) { | |
console.error(error); | |
throw new Error(`createBinanceOcoOrder: Could not parse orders from Binance response. Response: ${response}`); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment