From ec4fa04b4cb9801e7a142a8b290b9e632f8f8b7e Mon Sep 17 00:00:00 2001 From: Zheng Chen Date: Fri, 3 May 2024 17:40:13 +0800 Subject: [PATCH] refactor: upgrade to new model (#42) --- @libs/global.ts | 3 - @libs/index.ts | 3 - @libs/utils/getClosePriceByDesiredProfit.ts | 8 +- @libs/utils/mergePositions.ts | 10 +- @libs/utils/useCounterParty.ts | 32 +-- @libs/utils/usePositionLimit.ts | 14 +- @libs/utils/useSimplePositionManager.ts | 40 +-- @libs/utils/useSinglePosition.ts | 60 ++-- @libs/utils/useStopLossOnSingleProduct.ts | 51 ++-- @models/R-Breaker.ts | 4 +- @models/consecutive-up-down.ts | 4 +- @models/greedy.ts | 4 +- @models/grid.ts | 14 +- @models/super-trend.ts | 4 +- @models/turtle-long.ts | 2 +- global.d.ts | 292 ++++++++++---------- 16 files changed, 251 insertions(+), 294 deletions(-) mode change 100755 => 100644 @models/grid.ts diff --git a/@libs/global.ts b/@libs/global.ts index 5366d70..5b57fd1 100644 --- a/@libs/global.ts +++ b/@libs/global.ts @@ -1,7 +1,4 @@ export const global = { - PositionVariant, - OrderDirection, - OrderType, useRef, useEffect, useMemo, diff --git a/@libs/index.ts b/@libs/index.ts index a2ff13f..f6525bd 100644 --- a/@libs/index.ts +++ b/@libs/index.ts @@ -15,9 +15,6 @@ export const useSeries = global.useSeries; export const useState = global.useState; export const formatTime = global.formatTime; export const UUID = global.UUID; -export const PositionVariant = global.PositionVariant; -export const OrderDirection = global.OrderDirection; -export const OrderType = global.OrderType; export * from "./constants/products"; export * from "./indicators/ATR"; diff --git a/@libs/utils/getClosePriceByDesiredProfit.ts b/@libs/utils/getClosePriceByDesiredProfit.ts index a929422..c619709 100644 --- a/@libs/utils/getClosePriceByDesiredProfit.ts +++ b/@libs/utils/getClosePriceByDesiredProfit.ts @@ -5,7 +5,7 @@ * @param openPrice - 开仓价 * @param volume - 成交量 * @param desiredProfit - 目标盈利 - * @param variant - 仓位类型 + * @param direction - 仓位方向 * @param currency - 账户货币 * @param quotes - 市场报价 * @returns - 目标平仓价 @@ -15,14 +15,14 @@ export const getClosePriceByDesiredProfit = ( openPrice: number, volume: number, desiredProfit: number, - variant: PositionVariant, + direction: string, currency: string, quotes: (product_id: string) => { ask: number; bid: number } | undefined ) => { - const variant_coefficient = variant === PositionVariant.LONG ? 1 : -1; + const variant_coefficient = direction === "LONG" ? 1 : -1; const cross_product_exchange_rate = product.quote_currency !== currency - ? (variant === PositionVariant.LONG + ? (direction === "LONG" ? quotes(`${product.quote_currency}${currency}`)?.bid : quotes(`${product.quote_currency}${currency}`)?.ask) ?? 1 : 1; diff --git a/@libs/utils/mergePositions.ts b/@libs/utils/mergePositions.ts index e8b5fbd..db6c046 100644 --- a/@libs/utils/mergePositions.ts +++ b/@libs/utils/mergePositions.ts @@ -7,11 +7,11 @@ */ export const mergePositions = (positions: IPosition[]): IPosition[] => { const mapProductIdToPosition = positions.reduce((acc, cur) => { - const { product_id, variant } = cur; - if (!acc[`${product_id}-${variant}`]) { - acc[`${product_id}-${variant}`] = { ...cur }; + const { product_id, direction } = cur; + if (!acc[`${product_id}-${direction}`]) { + acc[`${product_id}-${direction}`] = { ...cur }; } else { - let thePosition = acc[`${product_id}-${variant}`]; + let thePosition = acc[`${product_id}-${direction}`]; thePosition = { ...thePosition, volume: thePosition.volume + cur.volume, @@ -26,7 +26,7 @@ export const mergePositions = (positions: IPosition[]): IPosition[] => { cur.closable_price * cur.volume) / (thePosition.volume + cur.volume), }; - acc[`${product_id}-${variant}`] = thePosition; + acc[`${product_id}-${direction}`] = thePosition; } return acc; }, {} as Record); diff --git a/@libs/utils/useCounterParty.ts b/@libs/utils/useCounterParty.ts index ebd4345..d687ebf 100644 --- a/@libs/utils/useCounterParty.ts +++ b/@libs/utils/useCounterParty.ts @@ -19,23 +19,23 @@ export function useCounterParty(source_account_id: string) { const theOrder = { ...order, account_id: tar.account_id, - client_order_id: UUID(), + order_id: UUID(), type: - order.type === OrderType.STOP - ? OrderType.LIMIT - : order.type === OrderType.LIMIT - ? OrderType.STOP - : order.type, + order.order_type === "STOP" + ? "LIMIT" + : order.order_type === "LIMIT" + ? "STOP" + : order.order_type, direction: - order.direction === OrderDirection.OPEN_LONG - ? OrderDirection.OPEN_SHORT - : order.direction === OrderDirection.OPEN_SHORT - ? OrderDirection.OPEN_LONG - : order.direction === OrderDirection.CLOSE_LONG - ? OrderDirection.CLOSE_SHORT - : order.direction === OrderDirection.CLOSE_SHORT - ? OrderDirection.CLOSE_LONG - : order.direction, + order.order_direction === "OPEN_LONG" + ? "OPEN_SHORT" + : order.order_direction === "OPEN_SHORT" + ? "OPEN_LONG" + : order.order_direction === "CLOSE_LONG" + ? "CLOSE_SHORT" + : order.order_direction === "CLOSE_SHORT" + ? "CLOSE_LONG" + : order.order_direction, }; ex.submitOrder(theOrder); orders.push(theOrder); @@ -43,7 +43,7 @@ export function useCounterParty(source_account_id: string) { } return () => { for (const order of orders) { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); } }; }); diff --git a/@libs/utils/usePositionLimit.ts b/@libs/utils/usePositionLimit.ts index e57bb72..a612bc9 100644 --- a/@libs/utils/usePositionLimit.ts +++ b/@libs/utils/usePositionLimit.ts @@ -16,23 +16,15 @@ export function usePositionLimit( currency: src.money.currency, leverage: src.money.leverage, }); - const pL = useSinglePosition( - product_id, - PositionVariant.LONG, - tar.account_id - ); - const pS = useSinglePosition( - product_id, - PositionVariant.SHORT, - tar.account_id - ); + const pL = useSinglePosition(product_id, "LONG", tar.account_id); + const pS = useSinglePosition(product_id, "SHORT", tar.account_id); useEffect(() => { const srcNetPosition = src.positions.reduce( (acc, cur) => acc + (cur.product_id !== product_id ? 0 - : cur.volume * (cur.variant === PositionVariant.LONG ? 1 : -1)), + : cur.volume * (cur.direction === "LONG" ? 1 : -1)), 0 ); pL.setTargetVolume( diff --git a/@libs/utils/useSimplePositionManager.ts b/@libs/utils/useSimplePositionManager.ts index 0eb0196..579e9d5 100644 --- a/@libs/utils/useSimplePositionManager.ts +++ b/@libs/utils/useSimplePositionManager.ts @@ -45,72 +45,72 @@ export const useSimplePositionManager = ( // OPEN LONG: submit & cancel order. useEffect(() => { if (openLongVolume <= 0) return; - const order = { - client_order_id: UUID(), + const order: IOrder = { + order_id: UUID(), account_id, product_id, position_id: longPositionId, - type: OrderType.MARKET, - direction: OrderDirection.OPEN_LONG, + order_type: "MARKET", + order_direction: "OPEN_LONG", volume: openLongVolume, }; exchange.submitOrder(order); return () => { - exchange.cancelOrder(order.client_order_id); + exchange.cancelOrder(order.order_id!); }; }, [openLongVolume]); // OPEN SHORT: submit & cancel order. useEffect(() => { if (openShortVolume <= 0) return; - const order = { - client_order_id: UUID(), + const order: IOrder = { + order_id: UUID(), account_id, product_id, position_id: shortPositionId, - type: OrderType.MARKET, - direction: OrderDirection.OPEN_SHORT, + order_type: "MARKET", + order_direction: "OPEN_SHORT", volume: openShortVolume, }; exchange.submitOrder(order); return () => { - exchange.cancelOrder(order.client_order_id); + exchange.cancelOrder(order.order_id!); }; }, [openShortVolume]); // CLOSE LONG: submit & cancel order. useEffect(() => { if (closeLongVolume <= 0) return; - const order = { - client_order_id: UUID(), + const order: IOrder = { + order_id: UUID(), account_id, product_id, position_id: longPositionId, - type: OrderType.MARKET, - direction: OrderDirection.CLOSE_LONG, + order_type: "MARKET", + order_direction: "CLOSE_LONG", volume: closeLongVolume, }; exchange.submitOrder(order); return () => { - exchange.cancelOrder(order.client_order_id); + exchange.cancelOrder(order.order_id!); }; }, [closeLongVolume]); // CLOSE SHORT: submit & cancel order. useEffect(() => { if (closeShortVolume <= 0) return; - const order = { - client_order_id: UUID(), + const order: IOrder = { + order_id: UUID(), account_id, product_id, position_id: shortPositionId, - type: OrderType.MARKET, - direction: OrderDirection.CLOSE_SHORT, + order_type: "MARKET", + order_direction: "CLOSE_SHORT", volume: closeShortVolume, }; exchange.submitOrder(order); return () => { - exchange.cancelOrder(order.client_order_id); + exchange.cancelOrder(order.order_id!); }; }, [closeShortVolume]); diff --git a/@libs/utils/useSinglePosition.ts b/@libs/utils/useSinglePosition.ts index 9c0cb25..1803293 100644 --- a/@libs/utils/useSinglePosition.ts +++ b/@libs/utils/useSinglePosition.ts @@ -5,7 +5,7 @@ */ export const useSinglePosition = ( product_id: string, - variant: PositionVariant, + direction: string, account_id?: string ): { targetVolume: number; @@ -24,7 +24,7 @@ export const useSinglePosition = ( ) || { position_id, product_id, - variant, + direction, volume: 0, free_volume: 0, position_price: NaN, @@ -46,14 +46,14 @@ export const useSinglePosition = ( useEffect(() => { if ( (takeProfitOrderRef.current && - !ex.getOrderById(takeProfitOrderRef.current.client_order_id)) || + !ex.getOrderById(takeProfitOrderRef.current.order_id!)) || (stopLossOrderRef.current && - !ex.getOrderById(stopLossOrderRef.current.client_order_id)) + !ex.getOrderById(stopLossOrderRef.current.order_id!)) ) { // cancel the rest ex.cancelOrder( - takeProfitOrderRef.current?.client_order_id || "", - stopLossOrderRef.current?.client_order_id || "" + takeProfitOrderRef.current?.order_id || "", + stopLossOrderRef.current?.order_id || "" ); takeProfitOrderRef.current = null; stopLossOrderRef.current = null; @@ -75,15 +75,13 @@ export const useSinglePosition = ( return; } const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: accountId, product_id: position.product_id, position_id: position.position_id, - type: OrderType.MARKET, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.OPEN_LONG - : OrderDirection.OPEN_SHORT, + order_type: "MARKET", + order_direction: + position.direction === "LONG" ? "OPEN_LONG" : "OPEN_SHORT", volume: roundToStep( targetVolumeRef.current - position.volume, volume_step @@ -91,7 +89,7 @@ export const useSinglePosition = ( }; ex.submitOrder(order); return () => { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); }; } if (targetVolumeRef.current < position.volume) { @@ -103,20 +101,18 @@ export const useSinglePosition = ( return; } const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: accountId, product_id: position.product_id, position_id: position.position_id, - type: OrderType.MARKET, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.CLOSE_LONG - : OrderDirection.CLOSE_SHORT, + order_type: "MARKET", + order_direction: + position.direction === "LONG" ? "CLOSE_LONG" : "CLOSE_SHORT", volume, }; if (order.volume) ex.submitOrder(order); return () => { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); }; } } @@ -126,15 +122,13 @@ export const useSinglePosition = ( useEffect(() => { if (takeProfitPriceRef.current && position.volume) { const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: accountId, product_id, position_id, - type: OrderType.LIMIT, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.CLOSE_LONG - : OrderDirection.CLOSE_SHORT, + order_type: "LIMIT", + order_direction: + position.direction === "LONG" ? "CLOSE_LONG" : "CLOSE_SHORT", price: takeProfitPriceRef.current, volume: position.volume, }; @@ -142,7 +136,7 @@ export const useSinglePosition = ( ex.submitOrder(order); return () => { takeProfitOrderRef.current = null; - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); }; } }, [takeProfitPriceRef.current, position.volume]); @@ -151,15 +145,13 @@ export const useSinglePosition = ( useEffect(() => { if (stopLossPriceRef.current && position.volume) { const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: accountId, product_id, position_id, - type: OrderType.STOP, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.CLOSE_LONG - : OrderDirection.CLOSE_SHORT, + order_type: "STOP", + order_direction: + position.direction === "LONG" ? "CLOSE_LONG" : "CLOSE_SHORT", price: stopLossPriceRef.current, volume: position.volume, }; @@ -167,7 +159,7 @@ export const useSinglePosition = ( ex.submitOrder(order); return () => { stopLossOrderRef.current = null; - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); }; } }, [stopLossPriceRef.current, position.volume]); diff --git a/@libs/utils/useStopLossOnSingleProduct.ts b/@libs/utils/useStopLossOnSingleProduct.ts index a3948a5..bbb1d29 100644 --- a/@libs/utils/useStopLossOnSingleProduct.ts +++ b/@libs/utils/useStopLossOnSingleProduct.ts @@ -26,7 +26,7 @@ export const useStopLossOnSingleProduct = ( useEffect(() => { if (hasStopped.current) return; for (const order of stopLossOrders.current.values()) { - const theOrder = ex.getOrderById(order.client_order_id); + const theOrder = ex.getOrderById(order.order_id!); if (!theOrder) { log("Triggered StopLoss Event"); hasStopped.current = true; @@ -34,8 +34,7 @@ export const useStopLossOnSingleProduct = ( const currentVolume = src.positions.reduce( (acc, cur) => cur.product_id === source_product_id - ? acc + - (cur.variant === PositionVariant.LONG ? 1 : -1) * cur.volume + ? acc + (cur.direction === "LONG" ? 1 : -1) * cur.volume : acc, 0 ); @@ -51,7 +50,7 @@ export const useStopLossOnSingleProduct = ( const currentVolume = src.positions.reduce( (acc, cur) => cur.product_id === source_product_id - ? acc + (cur.variant === PositionVariant.LONG ? 1 : -1) * cur.volume + ? acc + (cur.direction === "LONG" ? 1 : -1) * cur.volume : acc, 0 ); @@ -63,15 +62,13 @@ export const useStopLossOnSingleProduct = ( const mergedPositions = mergePositions(src.positions); for (const position of mergedPositions) { const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: tar.account_id, product_id: position.product_id, position_id: position.position_id, - type: OrderType.MARKET, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.OPEN_LONG - : OrderDirection.OPEN_SHORT, + order_type: "MARKET", + order_direction: + position.direction === "LONG" ? "OPEN_LONG" : "OPEN_SHORT", volume: position.volume, }; ex.submitOrder(order); @@ -94,34 +91,32 @@ export const useStopLossOnSingleProduct = ( position.position_price, position.volume, -(drawdown_quota - position.floating_profit), - position.variant, + position.direction!, tar.money.currency, (product_id) => ex.getQuote(source_account_id, product_id) || { ask: 1, bid: 1 } ); mapProductIdVariantToClosePrice[ - `${position.product_id}${position.variant}` + `${position.product_id}${position.direction}` ] = price; } // ISSUE: 需要按照计算好的平仓价格分别平掉每一个头寸 for (const position of tar.positions) { const closePrice = mapProductIdVariantToClosePrice[ - `${position.product_id}${position.variant}` + `${position.product_id}${position.direction}` ]; if (Number.isNaN(closePrice)) { continue; } const order: IOrder = { - client_order_id: UUID(), + order_id: UUID(), account_id: tar.account_id, product_id: position.product_id, position_id: position.position_id, - type: OrderType.STOP, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.CLOSE_LONG - : OrderDirection.CLOSE_SHORT, + order_type: "STOP", + order_direction: + position.direction === "LONG" ? "CLOSE_LONG" : "CLOSE_SHORT", volume: position.volume, price: closePrice, }; @@ -130,7 +125,7 @@ export const useStopLossOnSingleProduct = ( ex.submitOrder(...stopLossOrders.current); return () => { stopLossOrders.current.forEach((order) => { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); }); stopLossOrders.current.clear(); }; @@ -143,14 +138,12 @@ export const useStopLossOnSingleProduct = ( const orders: IOrder[] = []; for (const position of tar.positions) { const order: IOrder = { + order_id: UUID(), account_id: tar.account_id, - client_order_id: UUID(), - type: OrderType.MARKET, + order_type: "MARKET", position_id: position.position_id, - direction: - position.variant === PositionVariant.LONG - ? OrderDirection.CLOSE_LONG - : OrderDirection.CLOSE_SHORT, + order_direction: + position.direction === "LONG" ? "CLOSE_LONG" : "CLOSE_SHORT", product_id: position.product_id, volume: position.volume, }; @@ -159,7 +152,7 @@ export const useStopLossOnSingleProduct = ( } return () => { for (const order of orders) { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); } }; }); @@ -173,7 +166,7 @@ export const useStopLossOnSingleProduct = ( const theOrder = { ...order, account_id: tar.account_id, - client_order_id: UUID(), + order_id: UUID(), volume: order.volume, }; ex.submitOrder(theOrder); @@ -182,7 +175,7 @@ export const useStopLossOnSingleProduct = ( } return () => { for (const order of orders) { - ex.cancelOrder(order.client_order_id); + ex.cancelOrder(order.order_id!); } }; }); diff --git a/@models/R-Breaker.ts b/@models/R-Breaker.ts index 2416002..bc2ea57 100644 --- a/@models/R-Breaker.ts +++ b/@models/R-Breaker.ts @@ -33,8 +33,8 @@ export default () => { _突破卖出价[i] = 突破卖出价; }); // 设置仓位管理器 - const pL = useSinglePosition(product_id, PositionVariant.LONG); - const pS = useSinglePosition(product_id, PositionVariant.SHORT); + const pL = useSinglePosition(product_id, "LONG"); + const pS = useSinglePosition(product_id, "SHORT"); const price = C[C.length - 1]; diff --git a/@models/consecutive-up-down.ts b/@models/consecutive-up-down.ts index 773e022..b8a3681 100644 --- a/@models/consecutive-up-down.ts +++ b/@models/consecutive-up-down.ts @@ -51,8 +51,8 @@ export default () => { } ); - const pL = useSinglePosition(product_id, PositionVariant.LONG); - const pS = useSinglePosition(product_id, PositionVariant.SHORT); + const pL = useSinglePosition(product_id, "LONG"); + const pS = useSinglePosition(product_id, "SHORT"); useEffect(() => { //如果连续上涨 diff --git a/@models/greedy.ts b/@models/greedy.ts index 9cf03fe..ec40ce5 100644 --- a/@models/greedy.ts +++ b/@models/greedy.ts @@ -6,8 +6,8 @@ import { useParamOHLC, useSinglePosition } from "@libs"; export default () => { const { product_id, open, high, low, close } = useParamOHLC("SomeKey"); - const pL = useSinglePosition(product_id, PositionVariant.LONG); - const pS = useSinglePosition(product_id, PositionVariant.SHORT); + const pL = useSinglePosition(product_id, "LONG"); + const pS = useSinglePosition(product_id, "SHORT"); const flag = useRef(0); useEffect(() => { diff --git a/@models/grid.ts b/@models/grid.ts old mode 100755 new mode 100644 index e189005..99a217d --- a/@models/grid.ts +++ b/@models/grid.ts @@ -32,24 +32,24 @@ export default () => { ); if (!thePosition && close[close.length - 1] > grid) { orders.push({ - client_order_id: UUID(), + order_id: UUID(), account_id: accountInfo.account_id, product_id, position_id: `${grid}`, - type: OrderType.LIMIT, - direction: OrderDirection.OPEN_LONG, + order_type: "LIMIT", + order_direction: "OPEN_LONG", volume: 1, price: grid, }); } if (thePosition) { orders.push({ - client_order_id: UUID(), + order_id: UUID(), account_id: accountInfo.account_id, product_id, position_id: `${grid}`, - type: OrderType.LIMIT, - direction: OrderDirection.CLOSE_LONG, + order_type: "LIMIT", + order_direction: "CLOSE_LONG", volume: 1, price: GRIDS[idx + 1], }); @@ -59,7 +59,7 @@ export default () => { exchange.submitOrder(...orders); return () => { for (const order of orders) { - exchange.cancelOrder(order.client_order_id); + exchange.cancelOrder(order.order_id!); } }; }); diff --git a/@models/super-trend.ts b/@models/super-trend.ts index 04ac85a..9c3a089 100644 --- a/@models/super-trend.ts +++ b/@models/super-trend.ts @@ -20,8 +20,8 @@ export default () => { const { ATR: atr } = useATR(high, low, close, 14); const idx = close.length - 2; - const pL = useSinglePosition(product_id, PositionVariant.LONG); - const pS = useSinglePosition(product_id, PositionVariant.SHORT); + const pL = useSinglePosition(product_id, "LONG"); + const pS = useSinglePosition(product_id, "SHORT"); const prevClose = (close[idx] + open[idx]) / 2; const upper = useSeriesMap( "Upper", diff --git a/@models/turtle-long.ts b/@models/turtle-long.ts index c85f97d..4d205d9 100644 --- a/@models/turtle-long.ts +++ b/@models/turtle-long.ts @@ -23,7 +23,7 @@ export default () => { const accountInfo = useAccountInfo(); - const pL = useSinglePosition(product_id, PositionVariant.LONG); + const pL = useSinglePosition(product_id, "LONG"); const { ATR } = useATR(high, low, close, 14); const price_break = useRef(0); const idx = close.length - 2; diff --git a/global.d.ts b/global.d.ts index 704ddf7..840e4f7 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,165 +1,225 @@ /** - * Order: Change the {@link IPosition} of {@link IAccountInfo} in the account through trading commands + * Order: Changes the {@link IPosition} of the {@link IAccountInfo} in the account through a trading command. + * 订单: 通过交易命令改变账户内 {@link IAccountInfo} 头寸 {@link IPosition} * @public */ declare interface IOrder { /** - * Client order ID + * Order ID */ - client_order_id: string; + order_id?: string; /** - * Exchange order ID (if any) - */ - exchange_order_id?: string; - /** - * Account ID + * Account ID. + * 账户 ID * * {@link IAccountInfo.account_id} */ account_id: string; /** - * Product ID + * Product ID. + * 品种 ID * * {@link IProduct} */ product_id: string; + /** - * Specify the position ID that needs to be operated + * Specifies the position ID to be operated on. + * 指定需要操作的头寸 ID * - * - If left blank, it means "which specific position under the same account and product can be operated" - * - If filled in, only the matching position can be operated, and other positions under the same account and product cannot be affected. + * - only the matching position can be operated on, and other positions under the same account and product cannot be affected. + * - 如果填写了,只能操作匹配的头寸,不得影响同账户下同品种下的其他头寸。 * * {@link IPosition.position_id} */ position_id?: string; - /** Order type */ - type: OrderType; - /** Order direction */ - direction: OrderDirection; - /** Commission volume */ - volume: number; /** - * Profit and loss correction under non-standard models - * - * When the profit and loss model is non-standard, a profit and loss correction value can be added to correct the standard model profit and loss to the actual profit and loss. - * - * Profit and loss correction = actual profit and loss - standard profit and loss - * - * If this value is empty, the semantics are equivalent to 0 - * - * Refer to [How to calculate profit and loss](https://tradelife.feishu.cn/wiki/wikcnRNzWSF7jtkH8nGruaMhhlh) + * Order matching type. * + * - `LIMIT`: Limits the price at which the order can be executed (default) + * - `MARKET`: Executed at the current market price + * - `STOP`: Triggers a market order when the market price reaches the order price + * - `FOK`: Requires immediate and complete + * - `IOC`: Requires immediate execution, allows partial execution, and cancels the rest */ - profit_correction?: number; + order_type?: string; /** - * Actual profit and loss - * - * When closing a position, the amount of change in the account balance + * Order direction. * - * If this value is empty, the semantics are equivalent to "profit and loss correction == 0", that is, "standard profit and loss == actual profit and loss" - * - * Refer to [How to calculate profit and loss](https://tradelife.feishu.cn/wiki/wikcnRNzWSF7jtkH8nGruaMhhlh) + * - `OPEN_LONG`: Open long position + * - `CLOSE_LONG`: Close long position + * - `OPEN_SHORT`: Open short position + * - `CLOSE_SHORT`: Close short position */ - real_profit?: number; + order_direction?: string; /** - * Inferred price of the base currency against the margin currency when closing the position - * - * if this value is empty, the semantics are equivalent to 1 (that is, the base currency == margin currency) - * - * Refer to [How to calculate profit and loss](https://tradelife.feishu.cn/wiki/wikcnRNzWSF7jtkH8nGruaMhhlh) + * Order volume. + * 委托量 */ - inferred_base_currency_price?: number; + volume: number; /** - * Order timestamp / transaction timestamp + * Submit order timestamp. */ - timestamp_in_us?: number; + submit_at?: number; /** - * Order price + * Order filled timestamp. + */ + filled_at?: number; + /** + * Order price. + * 委托价 */ price?: number; /** - * Traded volume + * Traded volume. + * 成交量 */ - /** 成交量 */ traded_volume?: number; /** - * Traded price + * Traded price. + * 成交价 */ traded_price?: number; /** - * Order status + * Order status. + * + * - `ACCEPTED`: Order accepted by the exchange + * - `TRADED`: Order partially filled + * - `CANCELLED`: Order cancelled */ - status?: OrderStatus; + order_status?: string; /** - * Order comment + * Order comment. + * 订单注释 */ comment?: string; + /** - * Take profit price + * Profit and loss correction in non-standard models. + * 非标准模型下的盈亏修正 + * + * When the profit and loss model is non-standard, + * a profit and loss correction value can be added to correct the standard model profit and loss to the actual profit and loss. + * 当盈亏模型非标准时,可以添加一个盈亏修正值,将标准模型盈亏修正到实际盈亏。 + * + * Profit and loss correction = actual profit and loss - standard profit and loss + * 盈亏修正 = 实际盈亏 - 标准盈亏 + * + * If this value is empty, it is semantically equivalent to 0. + * 如果此值为空,语义等同于 0 + */ + profit_correction?: number; + + /** + * Actual profit and loss. + * 实际盈亏 + * + * The amount of change in the account balance when closing a position. + * 平仓时,对账户的余额产生的改变量 + * + * If this value is empty, it is semantically equivalent to "profit_correction == 0", i.e., "standard profit and loss == actual profit and loss". + * 如果此值为空,语义等同于 "盈亏修正 == 0" 即 "标准盈亏 == 实际盈亏" + */ + real_profit?: number; + + /** + * The inferred price of the base currency against the margin currency at the time of closing the position. + * 推断得到的平仓时基准货币兑保证金货币的价格 + * + * If this value is empty, it is semantically equivalent to 1 (i.e., the base currency is the same as the margin currency). + * 如果此值为空,语义等同于 1 (即基准货币 == 保证金货币) + */ + inferred_base_currency_price?: number; + /** + * Take profit price (ignored for now). + * 止盈价 (暂时不可用) + * @deprecated to remove */ take_profit_price?: number; /** - * Stop loss price + * Stop loss price (ignored for now). + * 止损价 (暂时不可用) + * @deprecated to remove */ stop_loss_price?: number; } + /** - * Position Variant - * @public - */ -declare enum PositionVariant { - /** Long */ - LONG = 0, - /** Short */ - SHORT = 1, -} -/** - * Atomic position information + * Position: Atomic position information. + * 原子性的持仓头寸信息 * - * Same product positions can be summed up into one position + * Positions on the same product can be aggregated. + * 相同品种上的头寸可以被合计 * * @public */ declare interface IPosition { /** - * Position ID + * Position ID. + * 头寸 ID */ position_id: string; /** - * Product ID + * Product ID. + * 品种 ID */ product_id: string; /** - * Position variant + * Position direction (LONG | SHORT) * - * can be used to calculate net position + * - `"LONG"`: Long position + * - `"SHORT"`: Short position */ - variant: PositionVariant; + direction?: string; /** - * Volume + * Position volume (non-negative). + * 持仓量 (非负) * - * Settlement net value should refer to this field + * When calculating net value, this field should be referenced. + * 结算净值时应参考此字段 */ volume: number; /** - * Tradable volume (non-negative) + * Tradable volume (non-negative). + * 可交易量 (非负) * - * This field should be checked when placing an order + * When placing an order, this field should be referenced. + * 下单时应检查此字段 * - * When the market is T+0 trading, it should be consistent with the volume field; - * When the market is T+1 trading, it may be smaller than the volume. + * For T+0 trading, this field should be consistent with the volume field; + * 市场为 T+0 交易时应当与 volume 字段一致; + * For T+1 trading, this field may be smaller than the volume field. + * 市场为 T+1 交易时,可能比 volume 小. */ free_volume: number; - /** Position cost price (the intrinsic meaning of the price can be obtained through product_id) */ + /** + * Position price. + * 持仓成本价 (可通过 product_id 得到价格的内在含义) + */ position_price: number; - /** Current closable settlement price */ + + /** + * The current closable settlement price. + * 当前可平仓结算价格 + */ closable_price: number; - /** Floating profit and loss of the position */ + + /** + * Floating profit and loss of the position. + * 持仓浮动盈亏 + */ floating_profit: number; + /** - * Remarks of the position + * the comment of the position. + * 头寸的备注 */ comment?: string; + + // Position is one of the reasons for occupying margin, + // but the calculation mechanism of margin is relatively complex, and the algorithms of various exchanges are different. + // Therefore, Yuan does not calculate the margin based on the final margin given by the exchange. + // margin: number; } /** * Tick: Market transaction data at a certain moment @@ -390,80 +450,6 @@ declare interface IProduct { spread?: number; } -/** - * 订单类型 - * @public - */ -declare enum OrderType { - /** - * Market Order: Executed at the current market price - * - * The most common and simple order type, no need to specify an order price - */ - MARKET = 0, - /** - * Limit Order: Limits the price at which the order can be executed - * - * - BUY LIMIT: The execution price will not be higher than the order price - * - SELL LIMIT: The execution price will not be lower than the order price - */ - LIMIT = 1, - /** - * Stop Order: Triggers a market order when the market price reaches the order price - * - * - BUY STOP: Place an order when the market price is higher than the order price - * - SELL STOP: Place an order when the market price is lower than the order price - */ - STOP = 2, - /** - * Fill or Kill: Requires immediate and complete - * - * It is required to be executed immediately and completely when placing an order, otherwise it will be cancelled - */ - FOK = 3, - /** - * Immediate or Cancel: Requires immediate execution, allows partial execution, and cancels the rest - * - * It is required to be executed immediately when placing an order, allows partial execution, and cancels the rest - */ - IOC = 4, -} - -/** - * 订单方向 - * @public - */ -declare enum OrderDirection { - /** - * Open long position - */ - OPEN_LONG = 0, - /** - * Close long position - */ - CLOSE_LONG = 1, - /** - * Open short position - */ - OPEN_SHORT = 2, - /** - * Close short position - */ - CLOSE_SHORT = 3, -} -/** - * 订单状态 - * @public - */ -declare enum OrderStatus { - /** 交易所已接受委托 */ - ACCEPTED = 0, - /** 已成交 */ - TRADED = 1, - /** 已撤单 */ - CANCELLED = 2, -} - // Basic Hooks /** * Use a reference to a variable to maintain a reference to the same value in all execution stages, similar to React.useRef