基于'remaningQuantity'减少并创建一个新数组

问题描述 投票:0回答:1

我有点卡在如何实现我想要的输出上。

我只是想得到一些关于如何解决这个问题的帮助,因为我是一名初级开发人员,正在尝试构建一个项目,我觉得我在这里把事情复杂化了,但仍然没有得到我想要的东西。

问题: 我有一大堆对象,这里是其中的一大块:

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);

我想要实现的是:

  1. 如果没有“originTrade”,则将同类中的第一个指定为 origin trade
  2. 在给定资产的 originTrade 中,将所有即将进行的交易添加到 linkedTrades[],如果数量(或余额)高于 0(因此我们知道头寸尚未完全平仓)
  3. 当达到 0 或低于 0 时,然后创建另一个“originTrade”对象并将所有即将到来的交易分配到 linkedTrades[]。

我挣扎的部分:

  • 我已经实现了将交易分配到初始 originTrade 并使用 reduce 将所有单个交易链接到该给定资产的 linkedTrades,但是当给定 originTrade 的 remainingQuantity 达到 0 或以下时,我缺乏如何实现这一点的想法0,然后创建另一个 originTrade 并开始将交易链接到新交易。

我觉得我在这一点上使代码过于复杂。 任何帮助将不胜感激!

这是我想要实现的预期输出:

 [
  {
    "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 并在控制台记录了它。

谢谢!

javascript typescript algorithm sorting reduce
1个回答
0
投票

这里有一个解决方案,它使用

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;
}, []);

游乐场链接

© www.soinside.com 2019 - 2024. All rights reserved.