@gbozee/ultimate 0.0.2-next.73 → 0.0.2-next.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +346 -17
- package/dist/index.d.ts +71 -0
- package/dist/index.js +346 -17
- package/dist/mcp-server.cjs +346 -17
- package/dist/mcp-server.js +346 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -72038,9 +72038,18 @@ class BaseExchange {
|
|
|
72038
72038
|
async previewSpotMarginHedge(_payload) {
|
|
72039
72039
|
throw new Error("Spot margin hedge preview is not supported on this exchange");
|
|
72040
72040
|
}
|
|
72041
|
+
async previewFuturesReplay(_payload) {
|
|
72042
|
+
throw new Error("Futures replay preview is not supported on this exchange");
|
|
72043
|
+
}
|
|
72041
72044
|
async placeSpotMarginHedge(_payload) {
|
|
72042
72045
|
throw new Error("Spot margin hedge placement is not supported on this exchange");
|
|
72043
72046
|
}
|
|
72047
|
+
async placeFuturesReplay(_payload) {
|
|
72048
|
+
throw new Error("Futures replay placement is not supported on this exchange");
|
|
72049
|
+
}
|
|
72050
|
+
async placeFuturesExactTrade(_payload) {
|
|
72051
|
+
throw new Error("Futures exact trade placement is not supported on this exchange");
|
|
72052
|
+
}
|
|
72044
72053
|
async placeSpotLimitOrders(_payload) {}
|
|
72045
72054
|
async buildCumulative(payload) {
|
|
72046
72055
|
const {
|
|
@@ -72449,19 +72458,198 @@ class BaseExchange {
|
|
|
72449
72458
|
// src/exchanges/binance/index.ts
|
|
72450
72459
|
var import_p_limit = __toESM(require_p_limit(), 1);
|
|
72451
72460
|
|
|
72452
|
-
// src/exchanges/binance/
|
|
72461
|
+
// src/exchanges/binance/futures-replay.ts
|
|
72453
72462
|
function roundNumber(value2, digits = 8) {
|
|
72454
72463
|
return Number(value2.toFixed(digits));
|
|
72455
72464
|
}
|
|
72456
|
-
|
|
72465
|
+
function parseNumber2(value2) {
|
|
72466
|
+
if (value2 === undefined || value2 === null || value2 === "")
|
|
72467
|
+
return;
|
|
72468
|
+
const parsed = Number(value2);
|
|
72469
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
72470
|
+
return;
|
|
72471
|
+
return roundNumber(parsed);
|
|
72472
|
+
}
|
|
72457
72473
|
function normalizeOrderInput(order) {
|
|
72474
|
+
const stop = parseNumber2(order.stop) ?? parseNumber2(order.stopPrice) ?? parseNumber2(order.triggerPrice);
|
|
72475
|
+
const type = order.type ? order.type.toUpperCase() : undefined;
|
|
72476
|
+
const quantity = order.quantity ?? order.qty ?? 0;
|
|
72477
|
+
return {
|
|
72478
|
+
price: roundNumber(Number(order.price)),
|
|
72479
|
+
quantity: roundNumber(Number(quantity)),
|
|
72480
|
+
...stop ? { stop } : {},
|
|
72481
|
+
...type && type !== "LIMIT" ? { type } : {}
|
|
72482
|
+
};
|
|
72483
|
+
}
|
|
72484
|
+
function sortReplayOrders(orders) {
|
|
72485
|
+
return [...orders].sort((left, right) => {
|
|
72486
|
+
const leftTrigger = left.stop ?? left.price;
|
|
72487
|
+
const rightTrigger = right.stop ?? right.price;
|
|
72488
|
+
if (leftTrigger !== rightTrigger)
|
|
72489
|
+
return leftTrigger - rightTrigger;
|
|
72490
|
+
if (left.price !== right.price)
|
|
72491
|
+
return left.price - right.price;
|
|
72492
|
+
return left.quantity - right.quantity;
|
|
72493
|
+
});
|
|
72494
|
+
}
|
|
72495
|
+
function buildReplayStopLimitPrice(payload) {
|
|
72496
|
+
const spread = payload.stop > 30000 ? 1.00005 : 1.0002;
|
|
72497
|
+
return roundNumber(payload.kind === "long" ? payload.stop * spread ** -1 : payload.stop * spread);
|
|
72498
|
+
}
|
|
72499
|
+
function normalizeRequestedEntryOrders(orders) {
|
|
72500
|
+
return sortReplayOrders(orders.map((order) => ({
|
|
72501
|
+
price: roundNumber(Number(order.price)),
|
|
72502
|
+
quantity: roundNumber(Number(order.quantity))
|
|
72503
|
+
})));
|
|
72504
|
+
}
|
|
72505
|
+
function normalizeRequestedStopOrders(payload) {
|
|
72506
|
+
return sortReplayOrders(payload.orders.map((order) => {
|
|
72507
|
+
const stop = parseNumber2(order.stop) ?? roundNumber(Number(order.price));
|
|
72508
|
+
return {
|
|
72509
|
+
price: order.price !== undefined ? roundNumber(Number(order.price)) : buildReplayStopLimitPrice({
|
|
72510
|
+
kind: payload.kind,
|
|
72511
|
+
stop
|
|
72512
|
+
}),
|
|
72513
|
+
quantity: roundNumber(Number(order.quantity)),
|
|
72514
|
+
stop,
|
|
72515
|
+
type: (order.type || "STOP").toUpperCase()
|
|
72516
|
+
};
|
|
72517
|
+
}));
|
|
72518
|
+
}
|
|
72519
|
+
function normalizeRequestedTakeProfitOrders(orders) {
|
|
72520
|
+
return sortReplayOrders(orders.map((order) => {
|
|
72521
|
+
const stop = parseNumber2(order.stop);
|
|
72522
|
+
const type = order.type?.toUpperCase();
|
|
72523
|
+
return {
|
|
72524
|
+
price: roundNumber(Number(order.price)),
|
|
72525
|
+
quantity: roundNumber(Number(order.quantity)),
|
|
72526
|
+
...stop ? { stop } : {},
|
|
72527
|
+
...type ? { type } : stop ? { type: "TAKE_PROFIT" } : {}
|
|
72528
|
+
};
|
|
72529
|
+
}));
|
|
72530
|
+
}
|
|
72531
|
+
function buildOrderKey(order) {
|
|
72532
|
+
return [
|
|
72533
|
+
order.type || "LIMIT",
|
|
72534
|
+
order.price,
|
|
72535
|
+
order.quantity,
|
|
72536
|
+
order.stop ?? ""
|
|
72537
|
+
].join(":");
|
|
72538
|
+
}
|
|
72539
|
+
function buildComparisonBucket(options) {
|
|
72540
|
+
const expected = sortReplayOrders(options.expected);
|
|
72541
|
+
const actual = sortReplayOrders(options.actual);
|
|
72542
|
+
const expected_keys = expected.map(buildOrderKey);
|
|
72543
|
+
const actual_keys = actual.map(buildOrderKey);
|
|
72458
72544
|
return {
|
|
72459
|
-
|
|
72460
|
-
|
|
72545
|
+
expected,
|
|
72546
|
+
actual,
|
|
72547
|
+
missing: expected_keys.filter((key) => !actual_keys.includes(key)),
|
|
72548
|
+
extra: actual_keys.filter((key) => !expected_keys.includes(key))
|
|
72549
|
+
};
|
|
72550
|
+
}
|
|
72551
|
+
function buildFuturesReplaySnapshot(payload) {
|
|
72552
|
+
const entry_side = payload.kind === "long" ? "buy" : "sell";
|
|
72553
|
+
const close_side = payload.kind === "long" ? "sell" : "buy";
|
|
72554
|
+
const entry_orders = [];
|
|
72555
|
+
const stop_orders = [];
|
|
72556
|
+
const take_profit_orders = [];
|
|
72557
|
+
for (const order of payload.open_orders) {
|
|
72558
|
+
if (order.kind !== payload.kind)
|
|
72559
|
+
continue;
|
|
72560
|
+
const normalized_order = normalizeOrderInput(order);
|
|
72561
|
+
const type = (normalized_order.type || "LIMIT").toUpperCase();
|
|
72562
|
+
if (order.side === entry_side) {
|
|
72563
|
+
entry_orders.push(normalized_order);
|
|
72564
|
+
continue;
|
|
72565
|
+
}
|
|
72566
|
+
if (order.side !== close_side)
|
|
72567
|
+
continue;
|
|
72568
|
+
if (type.includes("TAKE_PROFIT") || normalized_order.stop === undefined) {
|
|
72569
|
+
take_profit_orders.push(normalized_order);
|
|
72570
|
+
continue;
|
|
72571
|
+
}
|
|
72572
|
+
stop_orders.push(normalized_order);
|
|
72573
|
+
}
|
|
72574
|
+
return {
|
|
72575
|
+
symbol: payload.symbol,
|
|
72576
|
+
kind: payload.kind,
|
|
72577
|
+
current_price: payload.current_price,
|
|
72578
|
+
position: payload.position,
|
|
72579
|
+
open_orders: payload.open_orders.filter((order) => order.kind === payload.kind),
|
|
72580
|
+
entry_orders: sortReplayOrders(entry_orders),
|
|
72581
|
+
stop_orders: sortReplayOrders(stop_orders),
|
|
72582
|
+
take_profit_orders: sortReplayOrders(take_profit_orders)
|
|
72583
|
+
};
|
|
72584
|
+
}
|
|
72585
|
+
function inferFuturesReplayInputFromLiveOrders(payload) {
|
|
72586
|
+
const snapshot = buildFuturesReplaySnapshot(payload);
|
|
72587
|
+
return {
|
|
72588
|
+
symbol: payload.symbol,
|
|
72589
|
+
kind: payload.kind,
|
|
72590
|
+
current_price: payload.current_price,
|
|
72591
|
+
position: payload.position,
|
|
72592
|
+
entry_orders: snapshot.entry_orders,
|
|
72593
|
+
stop_orders: snapshot.stop_orders,
|
|
72594
|
+
take_profit_orders: snapshot.take_profit_orders
|
|
72595
|
+
};
|
|
72596
|
+
}
|
|
72597
|
+
function compareFuturesReplayOrders(payload) {
|
|
72598
|
+
const entry = buildComparisonBucket({
|
|
72599
|
+
expected: payload.entry_orders,
|
|
72600
|
+
actual: payload.snapshot.entry_orders
|
|
72601
|
+
});
|
|
72602
|
+
const stop = buildComparisonBucket({
|
|
72603
|
+
expected: payload.stop_orders,
|
|
72604
|
+
actual: payload.snapshot.stop_orders
|
|
72605
|
+
});
|
|
72606
|
+
const take_profit = buildComparisonBucket({
|
|
72607
|
+
expected: payload.take_profit_orders,
|
|
72608
|
+
actual: payload.snapshot.take_profit_orders
|
|
72609
|
+
});
|
|
72610
|
+
return {
|
|
72611
|
+
matches: entry.missing.length === 0 && entry.extra.length === 0 && stop.missing.length === 0 && stop.extra.length === 0 && take_profit.missing.length === 0 && take_profit.extra.length === 0,
|
|
72612
|
+
entry,
|
|
72613
|
+
stop,
|
|
72614
|
+
take_profit
|
|
72615
|
+
};
|
|
72616
|
+
}
|
|
72617
|
+
function buildFuturesReplayPlan(payload) {
|
|
72618
|
+
return {
|
|
72619
|
+
symbol: payload.symbol,
|
|
72620
|
+
kind: payload.kind,
|
|
72621
|
+
orders_to_cancel: payload.snapshot.open_orders,
|
|
72622
|
+
orders_to_create: {
|
|
72623
|
+
entry: sortReplayOrders(payload.entry_orders),
|
|
72624
|
+
stop: sortReplayOrders(payload.stop_orders),
|
|
72625
|
+
take_profit: sortReplayOrders(payload.take_profit_orders)
|
|
72626
|
+
}
|
|
72627
|
+
};
|
|
72628
|
+
}
|
|
72629
|
+
function normalizeFuturesReplayInput(payload) {
|
|
72630
|
+
return {
|
|
72631
|
+
entry_orders: normalizeRequestedEntryOrders(payload.entry_orders),
|
|
72632
|
+
stop_orders: normalizeRequestedStopOrders({
|
|
72633
|
+
kind: payload.kind,
|
|
72634
|
+
orders: payload.stop_orders
|
|
72635
|
+
}),
|
|
72636
|
+
take_profit_orders: normalizeRequestedTakeProfitOrders(payload.take_profit_orders)
|
|
72637
|
+
};
|
|
72638
|
+
}
|
|
72639
|
+
|
|
72640
|
+
// src/exchanges/binance/spot-margin-hedge.ts
|
|
72641
|
+
function roundNumber2(value2, digits = 8) {
|
|
72642
|
+
return Number(value2.toFixed(digits));
|
|
72643
|
+
}
|
|
72644
|
+
var STOP_LIMIT_SPREAD_PERCENT = 0.0005;
|
|
72645
|
+
function normalizeOrderInput2(order) {
|
|
72646
|
+
return {
|
|
72647
|
+
price: roundNumber2(order.price),
|
|
72648
|
+
quantity: roundNumber2(order.quantity)
|
|
72461
72649
|
};
|
|
72462
72650
|
}
|
|
72463
72651
|
function sortOrderInputs(orders) {
|
|
72464
|
-
return [...orders].map(
|
|
72652
|
+
return [...orders].map(normalizeOrderInput2).sort((left, right) => left.price - right.price);
|
|
72465
72653
|
}
|
|
72466
72654
|
function normalizeOrderForComparison(order) {
|
|
72467
72655
|
const type = (order.type || "limit").toLowerCase();
|
|
@@ -72470,9 +72658,9 @@ function normalizeOrderForComparison(order) {
|
|
|
72470
72658
|
return {
|
|
72471
72659
|
side: order.side,
|
|
72472
72660
|
type,
|
|
72473
|
-
price:
|
|
72474
|
-
quantity:
|
|
72475
|
-
stop: parsed_stop !== undefined && Number.isFinite(parsed_stop) && parsed_stop > 0 ?
|
|
72661
|
+
price: roundNumber2(order.price),
|
|
72662
|
+
quantity: roundNumber2(order.quantity),
|
|
72663
|
+
stop: parsed_stop !== undefined && Number.isFinite(parsed_stop) && parsed_stop > 0 ? roundNumber2(parsed_stop) : undefined
|
|
72476
72664
|
};
|
|
72477
72665
|
}
|
|
72478
72666
|
function normalizeOrders(orders) {
|
|
@@ -72495,7 +72683,7 @@ function toPlannedOrders(orders) {
|
|
|
72495
72683
|
stop: order.stop
|
|
72496
72684
|
}));
|
|
72497
72685
|
}
|
|
72498
|
-
function
|
|
72686
|
+
function buildOrderKey2(order) {
|
|
72499
72687
|
return [
|
|
72500
72688
|
order.side,
|
|
72501
72689
|
order.type,
|
|
@@ -72505,8 +72693,8 @@ function buildOrderKey(order) {
|
|
|
72505
72693
|
].join(":");
|
|
72506
72694
|
}
|
|
72507
72695
|
function buildDiff(options) {
|
|
72508
|
-
const expectedKeys = options.expected.map(
|
|
72509
|
-
const actualKeys = options.actual.map(
|
|
72696
|
+
const expectedKeys = options.expected.map(buildOrderKey2);
|
|
72697
|
+
const actualKeys = options.actual.map(buildOrderKey2);
|
|
72510
72698
|
return {
|
|
72511
72699
|
missing: expectedKeys.filter((key) => !actualKeys.includes(key)),
|
|
72512
72700
|
extra: actualKeys.filter((key) => !expectedKeys.includes(key))
|
|
@@ -72518,10 +72706,10 @@ function getQuoteAsset(symbol) {
|
|
|
72518
72706
|
return target || symbol.slice(-4);
|
|
72519
72707
|
}
|
|
72520
72708
|
function sumNotional(orders) {
|
|
72521
|
-
return
|
|
72709
|
+
return roundNumber2(orders.reduce((sum, order) => sum + order.price * order.quantity, 0), 8);
|
|
72522
72710
|
}
|
|
72523
72711
|
function sumQuantity(orders) {
|
|
72524
|
-
return
|
|
72712
|
+
return roundNumber2(orders.reduce((sum, order) => sum + order.quantity, 0), 8);
|
|
72525
72713
|
}
|
|
72526
72714
|
function buildLongOrderPlacement(options) {
|
|
72527
72715
|
const { order, current_price } = options;
|
|
@@ -72530,7 +72718,7 @@ function buildLongOrderPlacement(options) {
|
|
|
72530
72718
|
side: "buy",
|
|
72531
72719
|
type: "stop_loss_limit",
|
|
72532
72720
|
price: order.price,
|
|
72533
|
-
stop:
|
|
72721
|
+
stop: roundNumber2(order.price * (1 - STOP_LIMIT_SPREAD_PERCENT)),
|
|
72534
72722
|
quantity: order.quantity
|
|
72535
72723
|
};
|
|
72536
72724
|
}
|
|
@@ -72598,11 +72786,11 @@ function buildSpotMarginHedgePlan(options) {
|
|
|
72598
72786
|
}));
|
|
72599
72787
|
const spot_orders_to_create = options.placement_overrides?.spot || default_spot_orders_to_create;
|
|
72600
72788
|
const margin_orders_to_create = options.placement_overrides?.margin || default_margin_orders_to_create;
|
|
72601
|
-
const borrow_delta =
|
|
72789
|
+
const borrow_delta = roundNumber2(Math.max(0, options.borrow_amount - options.snapshot.borrowed_quote_amount));
|
|
72602
72790
|
const spot_long_notional = sumNotional(spot_long_orders);
|
|
72603
|
-
const transfer_to_spot_amount =
|
|
72791
|
+
const transfer_to_spot_amount = roundNumber2(Math.max(0, spot_long_notional - options.snapshot.spot_quote_free));
|
|
72604
72792
|
const short_quantity = sumQuantity(short_orders);
|
|
72605
|
-
const transfer_base_to_spot_amount =
|
|
72793
|
+
const transfer_base_to_spot_amount = roundNumber2(Math.max(0, short_quantity - options.snapshot.spot_base_free));
|
|
72606
72794
|
return {
|
|
72607
72795
|
borrow_amount: options.borrow_amount,
|
|
72608
72796
|
borrow_delta,
|
|
@@ -74261,6 +74449,30 @@ class BinanceExchange extends BaseExchange {
|
|
|
74261
74449
|
throw error;
|
|
74262
74450
|
}
|
|
74263
74451
|
}
|
|
74452
|
+
async getFuturesSymbolFormats(symbol) {
|
|
74453
|
+
if (typeof this.client.getExchangeInfo !== "function") {
|
|
74454
|
+
return {
|
|
74455
|
+
price_places: "%.8f",
|
|
74456
|
+
decimal_places: "%.8f"
|
|
74457
|
+
};
|
|
74458
|
+
}
|
|
74459
|
+
try {
|
|
74460
|
+
const exchange_info = await this.client.getExchangeInfo();
|
|
74461
|
+
const symbol_info = exchange_info?.symbols?.find((item) => item.symbol === symbol.toUpperCase());
|
|
74462
|
+
const price_filter = symbol_info?.filters?.find((filter) => filter.filterType === "PRICE_FILTER");
|
|
74463
|
+
const lot_size_filter = symbol_info?.filters?.find((filter) => filter.filterType === "LOT_SIZE");
|
|
74464
|
+
return {
|
|
74465
|
+
price_places: getPrintfFormatFromStepSize(price_filter?.tickSize, "%.8f"),
|
|
74466
|
+
decimal_places: getPrintfFormatFromStepSize(lot_size_filter?.stepSize, "%.8f")
|
|
74467
|
+
};
|
|
74468
|
+
} catch (error) {
|
|
74469
|
+
console.error("Error fetching futures symbol formats:", error);
|
|
74470
|
+
return {
|
|
74471
|
+
price_places: "%.8f",
|
|
74472
|
+
decimal_places: "%.8f"
|
|
74473
|
+
};
|
|
74474
|
+
}
|
|
74475
|
+
}
|
|
74264
74476
|
async getSpotSymbolFormats(symbol) {
|
|
74265
74477
|
if (!this.main_client || typeof this.main_client.getExchangeInfo !== "function") {
|
|
74266
74478
|
return {
|
|
@@ -74315,6 +74527,123 @@ class BinanceExchange extends BaseExchange {
|
|
|
74315
74527
|
}
|
|
74316
74528
|
return await getMarginOpenOrders(this.main_client, symbol, isIsolated);
|
|
74317
74529
|
}
|
|
74530
|
+
async getFuturesReplaySnapshot(payload) {
|
|
74531
|
+
const symbol = payload.symbol.toUpperCase();
|
|
74532
|
+
const [open_orders, position_info, current_price] = await Promise.all([
|
|
74533
|
+
this.getOpenOrders({ symbol }),
|
|
74534
|
+
this.getPositionInfo(symbol),
|
|
74535
|
+
this.getCurrentPrice(symbol)
|
|
74536
|
+
]);
|
|
74537
|
+
return buildFuturesReplaySnapshot({
|
|
74538
|
+
symbol,
|
|
74539
|
+
kind: payload.kind,
|
|
74540
|
+
current_price,
|
|
74541
|
+
position: {
|
|
74542
|
+
size: position_info[payload.kind]?.size || 0
|
|
74543
|
+
},
|
|
74544
|
+
open_orders
|
|
74545
|
+
});
|
|
74546
|
+
}
|
|
74547
|
+
async previewFuturesReplay(payload) {
|
|
74548
|
+
const snapshot = payload.snapshot ? {
|
|
74549
|
+
...payload.snapshot,
|
|
74550
|
+
current_price: payload.snapshot.current_price ?? await this.getCurrentPrice(payload.symbol)
|
|
74551
|
+
} : await this.getFuturesReplaySnapshot({
|
|
74552
|
+
symbol: payload.symbol,
|
|
74553
|
+
kind: payload.kind
|
|
74554
|
+
});
|
|
74555
|
+
const shouldInferEntryOrders = !payload.entry_orders || payload.entry_orders.length === 0;
|
|
74556
|
+
const shouldInferStopOrders = !payload.stop_orders || payload.stop_orders.length === 0;
|
|
74557
|
+
const shouldInferTakeProfitOrders = !payload.take_profit_orders || payload.take_profit_orders.length === 0;
|
|
74558
|
+
const inferred_input = shouldInferEntryOrders || shouldInferStopOrders || shouldInferTakeProfitOrders ? inferFuturesReplayInputFromLiveOrders({
|
|
74559
|
+
symbol: payload.symbol,
|
|
74560
|
+
kind: payload.kind,
|
|
74561
|
+
current_price: snapshot.current_price,
|
|
74562
|
+
position: snapshot.position,
|
|
74563
|
+
open_orders: snapshot.open_orders
|
|
74564
|
+
}) : undefined;
|
|
74565
|
+
const explicit_input = normalizeFuturesReplayInput({
|
|
74566
|
+
kind: payload.kind,
|
|
74567
|
+
entry_orders: payload.entry_orders || [],
|
|
74568
|
+
stop_orders: payload.stop_orders || [],
|
|
74569
|
+
take_profit_orders: payload.take_profit_orders || []
|
|
74570
|
+
});
|
|
74571
|
+
const entry_orders = shouldInferEntryOrders ? inferred_input?.entry_orders || [] : explicit_input.entry_orders;
|
|
74572
|
+
const stop_orders = shouldInferStopOrders ? inferred_input?.stop_orders || [] : explicit_input.stop_orders;
|
|
74573
|
+
const take_profit_orders = shouldInferTakeProfitOrders ? inferred_input?.take_profit_orders || [] : explicit_input.take_profit_orders;
|
|
74574
|
+
const requested_input = {
|
|
74575
|
+
symbol: payload.symbol,
|
|
74576
|
+
kind: payload.kind,
|
|
74577
|
+
entry_orders,
|
|
74578
|
+
stop_orders,
|
|
74579
|
+
take_profit_orders
|
|
74580
|
+
};
|
|
74581
|
+
const plan = buildFuturesReplayPlan({
|
|
74582
|
+
...requested_input,
|
|
74583
|
+
snapshot
|
|
74584
|
+
});
|
|
74585
|
+
const comparison = compareFuturesReplayOrders({
|
|
74586
|
+
...requested_input,
|
|
74587
|
+
snapshot
|
|
74588
|
+
});
|
|
74589
|
+
return {
|
|
74590
|
+
snapshot,
|
|
74591
|
+
inferred_input,
|
|
74592
|
+
requested_input,
|
|
74593
|
+
plan,
|
|
74594
|
+
comparison
|
|
74595
|
+
};
|
|
74596
|
+
}
|
|
74597
|
+
async placeFuturesReplay(payload) {
|
|
74598
|
+
const preview = await this.previewFuturesReplay(payload);
|
|
74599
|
+
if (!payload.place) {
|
|
74600
|
+
return preview;
|
|
74601
|
+
}
|
|
74602
|
+
const symbol = payload.symbol.toUpperCase();
|
|
74603
|
+
await cancelAllOrders(this.client, symbol, {
|
|
74604
|
+
kind: payload.kind
|
|
74605
|
+
});
|
|
74606
|
+
const refreshed_snapshot = await this.getFuturesReplaySnapshot({
|
|
74607
|
+
symbol,
|
|
74608
|
+
kind: payload.kind
|
|
74609
|
+
});
|
|
74610
|
+
const execution_plan = buildFuturesReplayPlan({
|
|
74611
|
+
symbol,
|
|
74612
|
+
kind: payload.kind,
|
|
74613
|
+
entry_orders: preview.requested_input.entry_orders,
|
|
74614
|
+
stop_orders: preview.requested_input.stop_orders,
|
|
74615
|
+
take_profit_orders: preview.requested_input.take_profit_orders,
|
|
74616
|
+
snapshot: refreshed_snapshot
|
|
74617
|
+
});
|
|
74618
|
+
const { price_places, decimal_places } = await this.getFuturesSymbolFormats(symbol);
|
|
74619
|
+
const entry_orders = execution_plan.orders_to_create.entry.map((order) => ({
|
|
74620
|
+
...order,
|
|
74621
|
+
side: payload.kind === "long" ? "buy" : "sell",
|
|
74622
|
+
kind: payload.kind
|
|
74623
|
+
}));
|
|
74624
|
+
const stop_orders = execution_plan.orders_to_create.stop.map((order) => ({
|
|
74625
|
+
...order,
|
|
74626
|
+
side: payload.kind === "long" ? "sell" : "buy",
|
|
74627
|
+
kind: payload.kind,
|
|
74628
|
+
type: order.type || "STOP"
|
|
74629
|
+
}));
|
|
74630
|
+
const take_profit_orders = execution_plan.orders_to_create.take_profit.map((order) => ({
|
|
74631
|
+
...order,
|
|
74632
|
+
side: payload.kind === "long" ? "sell" : "buy",
|
|
74633
|
+
kind: payload.kind,
|
|
74634
|
+
...order.stop ? { type: order.type || "TAKE_PROFIT" } : {}
|
|
74635
|
+
}));
|
|
74636
|
+
const execution = entry_orders.length > 0 || stop_orders.length > 0 || take_profit_orders.length > 0 ? await createLimitPurchaseOrdersParallel(this.client, symbol, price_places, decimal_places, [...entry_orders, ...stop_orders, ...take_profit_orders]) : [];
|
|
74637
|
+
return {
|
|
74638
|
+
...preview,
|
|
74639
|
+
execution_plan,
|
|
74640
|
+
refreshed_snapshot,
|
|
74641
|
+
execution
|
|
74642
|
+
};
|
|
74643
|
+
}
|
|
74644
|
+
async placeFuturesExactTrade(payload) {
|
|
74645
|
+
return await this.placeFuturesReplay(payload);
|
|
74646
|
+
}
|
|
74318
74647
|
async getSpotMarginHedgeSnapshot(payload) {
|
|
74319
74648
|
if (!this.main_client) {
|
|
74320
74649
|
throw new Error("Main client not available for spot and margin trading");
|
package/dist/index.d.ts
CHANGED
|
@@ -387,6 +387,29 @@ declare abstract class BaseExchange {
|
|
|
387
387
|
max_spot_buy_orders?: number;
|
|
388
388
|
snapshot?: any;
|
|
389
389
|
}): Promise<any>;
|
|
390
|
+
previewFuturesReplay(_payload: {
|
|
391
|
+
symbol: string;
|
|
392
|
+
kind: "long" | "short";
|
|
393
|
+
entry_orders?: Array<{
|
|
394
|
+
price: number;
|
|
395
|
+
quantity: number;
|
|
396
|
+
stop?: number;
|
|
397
|
+
type?: string;
|
|
398
|
+
}>;
|
|
399
|
+
stop_orders?: Array<{
|
|
400
|
+
price?: number;
|
|
401
|
+
quantity: number;
|
|
402
|
+
stop?: number;
|
|
403
|
+
type?: string;
|
|
404
|
+
}>;
|
|
405
|
+
take_profit_orders?: Array<{
|
|
406
|
+
price: number;
|
|
407
|
+
quantity: number;
|
|
408
|
+
stop?: number;
|
|
409
|
+
type?: string;
|
|
410
|
+
}>;
|
|
411
|
+
snapshot?: any;
|
|
412
|
+
}): Promise<any>;
|
|
390
413
|
placeSpotMarginHedge(_payload: {
|
|
391
414
|
borrow_amount?: number;
|
|
392
415
|
symbol: string;
|
|
@@ -403,6 +426,54 @@ declare abstract class BaseExchange {
|
|
|
403
426
|
snapshot?: any;
|
|
404
427
|
place?: boolean;
|
|
405
428
|
}): Promise<any>;
|
|
429
|
+
placeFuturesReplay(_payload: {
|
|
430
|
+
symbol: string;
|
|
431
|
+
kind: "long" | "short";
|
|
432
|
+
entry_orders?: Array<{
|
|
433
|
+
price: number;
|
|
434
|
+
quantity: number;
|
|
435
|
+
stop?: number;
|
|
436
|
+
type?: string;
|
|
437
|
+
}>;
|
|
438
|
+
stop_orders?: Array<{
|
|
439
|
+
price?: number;
|
|
440
|
+
quantity: number;
|
|
441
|
+
stop?: number;
|
|
442
|
+
type?: string;
|
|
443
|
+
}>;
|
|
444
|
+
take_profit_orders?: Array<{
|
|
445
|
+
price: number;
|
|
446
|
+
quantity: number;
|
|
447
|
+
stop?: number;
|
|
448
|
+
type?: string;
|
|
449
|
+
}>;
|
|
450
|
+
snapshot?: any;
|
|
451
|
+
place?: boolean;
|
|
452
|
+
}): Promise<any>;
|
|
453
|
+
placeFuturesExactTrade(_payload: {
|
|
454
|
+
symbol: string;
|
|
455
|
+
kind: "long" | "short";
|
|
456
|
+
entry_orders?: Array<{
|
|
457
|
+
price: number;
|
|
458
|
+
quantity: number;
|
|
459
|
+
stop?: number;
|
|
460
|
+
type?: string;
|
|
461
|
+
}>;
|
|
462
|
+
stop_orders?: Array<{
|
|
463
|
+
price?: number;
|
|
464
|
+
quantity: number;
|
|
465
|
+
stop?: number;
|
|
466
|
+
type?: string;
|
|
467
|
+
}>;
|
|
468
|
+
take_profit_orders?: Array<{
|
|
469
|
+
price: number;
|
|
470
|
+
quantity: number;
|
|
471
|
+
stop?: number;
|
|
472
|
+
type?: string;
|
|
473
|
+
}>;
|
|
474
|
+
snapshot?: any;
|
|
475
|
+
place?: boolean;
|
|
476
|
+
}): Promise<any>;
|
|
406
477
|
placeSpotLimitOrders(_payload: any): Promise<void>;
|
|
407
478
|
buildCumulative(payload: {
|
|
408
479
|
orders: Order$1[];
|