我有点卡在如何实现我想要的输出上。
我只是想得到一些关于如何解决这个问题的帮助,因为我是一名初级开发人员,正在尝试构建一个项目,我觉得我在这里把事情复杂化了,但仍然没有得到我想要的东西。
问题: 我有一大堆对象,这里是其中的一大块:
const trades: Trade[] = [
{ side: 'BUY', asset: 'ETH', quantity: 50, price: 1800 },
{ side: 'BUY', asset: 'ETH', quantity: 20, price: 1850 },
{ side: 'SELL', asset: 'BTC', quantity: 25, price: 36800 },
{ side: 'SELL', asset: 'ETH', quantity: 5, price: 1900 },
{ side: 'BUY', asset: 'BTC', quantity: 10, price: 37000 },
{ side: 'SELL', asset: 'ETH', quantity: 40, price: 1700 },
{ side: 'SELL', asset: 'ETH', quantity: 25, price: 1750 },
{ side: 'BUY', asset: 'BTC', quantity: 15, price: 35000 },
{ side: 'BUY', asset: 'BTC', quantity: 5, price: 39000 },
{ side: 'SELL', asset: 'BTC', quantity: 5, price: 38500 },
{ side: 'SELL', asset: 'ETH', quantity: 80, price: 1350 },
];
接口:
interface OriginTrade {
side: 'BUY' | 'SELL';
asset: string;
quantity: number;
remainingQuantity: number;
linkedTrades: MatchedTrade[];
}
interface MatchedTrade {
trade: Trade;
remainingQuantity: number;
index: number;
}
interface Trade {
side: 'BUY' | 'SELL';
asset: string;
quantity: number;
price: number;
}
代码本身:
const originTrades: OriginTrade[] = trades.reduce<OriginTrade[]>(
(acc, curr, i) => {
const { side, asset, quantity } = curr;
if (!acc[asset]) {
const originQuantity = side === 'SELL' ? -quantity : quantity; // transform quantity into negative if side is SELL
acc[asset] = curr; // If there is no existing origin trade for this asset, set the current trade as the origin trade
// and push the trades into the array
acc.push({
side: side,
asset: asset,
quantity: originQuantity,
linkedTrades: [],
remainingQuantity: originQuantity,
});
} else {
// if there is an existing previous trade get it and also the side
// const existingTrade = acc[asset];
const existingTrade = acc.find((trade) => trade.asset === asset)!;
// set the math operator based on the side
const operator = curr.side === 'BUY' ? '+' : '-';
// then use that operator to calculate remaining quantity
const calculateRemainingQuantity = eval(existingTrade.remainingQuantity + operator + quantity);
// set the quantity of the current trade based on the side
curr.quantity = curr.side === 'SELL' ? -curr.quantity : curr.quantity;
// const existingTradeSide = existingTrade.side;
existingTrade.linkedTrades.push({ trade: curr, remainingQuantity: calculateRemainingQuantity, index: existingTrade.linkedTrades.length });
existingTrade.remainingQuantity = calculateRemainingQuantity;
}
return acc;
},
[]
);
console.log('actuall output', originTrades);
我想要实现的是:
我挣扎的部分:
我觉得我在这一点上使代码过于复杂。 任何帮助将不胜感激!
这是我想要实现的预期输出:
[
{
"side": "BUY",
"asset": "ETH",
"quantity": 50,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "ETH",
"quantity": 20,
"price": 1850
},
"remainingQuantity": 70,
"index": 0
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -5,
"price": 1900
},
"remainingQuantity": 65,
"index": 1
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -40,
"price": 1700
},
"remainingQuantity": 25,
"index": 2
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -25,
"price": 1750
},
"remainingQuantity": 0,
"index": 3
}
],
"remainingQuantity": 0
},
{
"side": "SELL",
"asset": "BTC",
"quantity": -25,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 10,
"price": 37000
},
"remainingQuantity": -15,
"index": 0
},
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 15,
"price": 35000
},
"remainingQuantity": 0,
"index": 1
}
],
"remainingQuantity": 0
},
{
"side": "SELL",
"asset": "ETH",
"quantity": -80,
"linkedTrades": [],
"remainingQuantity": -80
},
{
"side": "BUY",
"asset": "BTC",
"quantity": 5,
"linkedTrades": [
{
"trade": {
"side": "SELL",
"asset": "BTC",
"quantity": -5,
"price": 38500
},
"remainingQuantity": 0,
"index": 3
}
],
"remainingQuantity": 0
}
]
这是我现在得到的输出:
[
{
"side": "BUY",
"asset": "ETH",
"quantity": 50,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "ETH",
"quantity": 20,
"price": 1850
},
"remainingQuantity": 70,
"index": 0
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -5,
"price": 1900
},
"remainingQuantity": 65,
"index": 1
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -40,
"price": 1700
},
"remainingQuantity": 25,
"index": 2
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -25,
"price": 1750
},
"remainingQuantity": 0,
"index": 3
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -80,
"price": 1350
},
"remainingQuantity": -80,
"index": 4
}
],
"remainingQuantity": -80
},
{
"side": "SELL",
"asset": "BTC",
"quantity": -25,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 10,
"price": 37000
},
"remainingQuantity": -15,
"index": 0
},
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 15,
"price": 35000
},
"remainingQuantity": 0,
"index": 1
},
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 5,
"price": 39000
},
"remainingQuantity": 5,
"index": 2
},
{
"trade": {
"side": "SELL",
"asset": "BTC",
"quantity": -5,
"price": 38500
},
"remainingQuantity": 0,
"index": 3
}
],
"remainingQuantity": 0
}
]
整个代码
在 TS 中:# https://playcode.io/1450531 这里在 SO 中使用 JS 编辑器:
const trades = [
{ side: 'BUY', asset: 'ETH', quantity: 50, price: 1800 }, // ORIGIN TRADE n1
{ side: 'BUY', asset: 'ETH', quantity: 20, price: 1850 }, // LINKED TO ORIGIN TRADE n1
{ side: 'SELL', asset: 'BTC', quantity: 25, price: 36800 }, // ORIGIN TRADE n2
{ side: 'SELL', asset: 'ETH', quantity: 5, price: 1900 }, // LINKED TO ORIGIN TRADE n1
{ side: 'BUY', asset: 'BTC', quantity: 10, price: 37000 }, // LINKED TO ORIGIN TRADE n2
{ side: 'SELL', asset: 'ETH', quantity: 40, price: 1700 }, // LINKED TO ORIGIN TRADE n1
{ side: 'SELL', asset: 'ETH', quantity: 25, price: 1750 }, // LINKED TO ORIGIN TRADE n1
{ side: 'BUY', asset: 'BTC', quantity: 15, price: 35000 }, // LINKED TO ORIGIN TRADE n2
{ side: 'BUY', asset: 'BTC', quantity: 5, price: 39000 }, // ORIGIN TRADE n3
{ side: 'SELL', asset: 'BTC', quantity: 5, price: 38500 },// LINKED TO ORIGIN TRADE n3
{ side: 'SELL', asset: 'ETH', quantity: 80, price: 1350 }, // ORIGIN TRADE n4
];
const originTrades = trades.reduce(
(acc, curr, i) => {
const { side, asset, quantity } = curr;
if (!acc[asset]) {
const originQuantity = side === 'SELL' ? -quantity : quantity; // transform quantity into negative if side is SELL
acc[asset] = curr; // If there is no existing origin trade for this asset, set the current trade as the origin trade
// and push the trades into the array
acc.push({
side: side,
asset: asset,
quantity: originQuantity,
linkedTrades: [],
remainingQuantity: originQuantity,
});
} else {
// if there is an existing previous trade get it and also the side
// const existingTrade = acc[asset];
const existingTrade = acc.find((trade) => trade.asset === asset);
// set the math operator based on the side
const operator = curr.side === 'BUY' ? '+' : '-';
// then use that operator to calculate remaining quantity
const calculateRemainingQuantity = eval(existingTrade.remainingQuantity + operator + quantity);
// set the quantity of the current trade based on the side
curr.quantity = curr.side === 'SELL' ? -curr.quantity : curr.quantity;
// const existingTradeSide = existingTrade.side;
existingTrade.linkedTrades.push({ trade: curr, remainingQuantity: calculateRemainingQuantity, index: existingTrade.linkedTrades.length });
existingTrade.remainingQuantity = calculateRemainingQuantity;
}
return acc;
},
[]
);
console.log('actuall output', originTrades);
const expectedOutput = [
{
"side": "BUY",
"asset": "ETH",
"quantity": 50,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "ETH",
"quantity": 20,
"price": 1850
},
"remainingQuantity": 70,
"index": 0
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -5,
"price": 1900
},
"remainingQuantity": 65,
"index": 1
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -40,
"price": 1700
},
"remainingQuantity": 25,
"index": 2
},
{
"trade": {
"side": "SELL",
"asset": "ETH",
"quantity": -25,
"price": 1750
},
"remainingQuantity": 0,
"index": 3
}
],
"remainingQuantity": 0
},
{
"side": "SELL",
"asset": "BTC",
"quantity": -25,
"linkedTrades": [
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 10,
"price": 37000
},
"remainingQuantity": -15,
"index": 0
},
{
"trade": {
"side": "BUY",
"asset": "BTC",
"quantity": 15,
"price": 35000
},
"remainingQuantity": 0,
"index": 1
}
],
"remainingQuantity": 0
},
{
"side": "SELL",
"asset": "ETH",
"quantity": -80,
"linkedTrades": [],
"remainingQuantity": -80
},
{
"side": "BUY",
"asset": "BTC",
"quantity": 5,
"linkedTrades": [
{
"trade": {
"side": "SELL",
"asset": "BTC",
"quantity": -5,
"price": 38500
},
"remainingQuantity": 0,
"index": 3
}
],
"remainingQuantity": 0
}
]
console.log('expected output', expectedOutput);
我还在最后添加了一个“expectedOutput”JSON 并在控制台记录了它。
谢谢!
findLast()
检查是否存在未平仓头寸。如果找到一个,它的 remainingQuantity
就会更新,并且一个元素被添加到它的 linkedTrades
中。如果没有找到,一个新的 OriginTrade
对象被添加到结果数组:
const result: OriginTrade[] = trades.reduce((a: OriginTrade[], v) => {
const { side, asset, quantity } = v;
const origin = a.findLast((v) => v.asset === asset
&& v.remainingQuantity !== 0);
const originQuantity = side === 'SELL' ? -quantity : quantity;
if (origin) {
origin.remainingQuantity += originQuantity;
origin.linkedTrades.push({
trade: v,
remainingQuantity: origin.remainingQuantity,
index: origin.linkedTrades.length
});
} else {
a.push({
side,
asset,
quantity,
remainingQuantity: originQuantity,
linkedTrades: []
});
}
return a;
}, []);