adjustOpenOrdersPrice(...pairStates) {
    for (const orderId in this.runningOrders) {
      if (this.runningOrders[orderId] < moment().subtract(2, 'minutes')) {
        this.logger.debug(`OrderAdjust: adjustOpenOrdersPrice timeout cleanup: ${JSON.stringify([orderId, this.runningOrders[orderId]])}`);

        delete this.runningOrders[orderId];
      }
    }

    const visitExchangeOrder = async pairState => {
      if (!pairState.hasAdjustedPrice()) {
        return;
      }

      const exchange = this.exchangeManager.get(pairState.getExchange());

      const exchangeOrder = pairState.getExchangeOrder();
      if (!exchangeOrder) {
        return;
      }

      if (exchangeOrder.id in this.runningOrders) {
        this.logger.info(`OrderAdjust: already running: ${JSON.stringify([exchangeOrder.id, pairState.getExchange(), pairState.getSymbol()])}`);
        return;
      }

      this.runningOrders[exchangeOrder.id] = new Date();

      const price = await this.getCurrentPrice(pairState.getExchange(), pairState.getSymbol(), exchangeOrder.getLongOrShortSide());
      if (!price) {
        this.logger.info(
          `OrderAdjust: No up to date ticker price found: ${JSON.stringify([
            exchangeOrder.id,
            pairState.getExchange(),
            pairState.getSymbol(),
            exchangeOrder.getLongOrShortSide()
          ])}`
        );

        delete this.runningOrders[exchangeOrder.id];

        return;
      }

      // order not known by exchange cleanup
      const lastExchangeOrder = await exchange.findOrderById(exchangeOrder.id);
      if (!lastExchangeOrder || lastExchangeOrder.status !== ExchangeOrder.STATUS_OPEN) {
        this.logger.debug(
          `OrderAdjust: managed order does not exists maybe filled; cleanup: ${JSON.stringify([
            exchangeOrder.id,
            pairState.getExchange(),
            pairState.getSymbol(),
            lastExchangeOrder
          ])}`
        );

        delete this.runningOrders[exchangeOrder.id];

        return;
      }

      const orderUpdate = Order.createPriceUpdateOrder(exchangeOrder.id, price, exchangeOrder.getLongOrShortSide());

      // normalize prices for positions compare; we can have negative prices depending on "side"
      if (Math.abs(lastExchangeOrder.price) === Math.abs(price)) {
        this.logger.info(
          `OrderAdjust: No price update needed:${JSON.stringify([
            lastExchangeOrder.id,
            Math.abs(lastExchangeOrder.price),
            Math.abs(price),
            pairState.getExchange(),
            pairState.getSymbol()
          ])}`
        );
        delete this.runningOrders[exchangeOrder.id];

        return;
      }

      try {
        const updatedOrder = await exchange.updateOrder(orderUpdate.id, orderUpdate);

        if (updatedOrder && updatedOrder.status === ExchangeOrder.STATUS_OPEN) {
          this.logger.info(
            `OrderAdjust: Order adjusted with orderbook price: ${JSON.stringify([
              updatedOrder.id,
              Math.abs(lastExchangeOrder.price),
              Math.abs(price),
              pairState.getExchange(),
              pairState.getSymbol(),
              updatedOrder
            ])}`
          );
          pairState.setExchangeOrder(updatedOrder);
        } else if (updatedOrder && updatedOrder.status === ExchangeOrder.STATUS_CANCELED && updatedOrder.retry === true) {
          // we update the price outside the orderbook price range on PostOnly we will cancel the order directly
          this.logger.error(`OrderAdjust: Updated order canceled recreate: ${JSON.stringify(pairState, updatedOrder)}`);

          // recreate order
          // @TODO: resync used balance in case on order is partially filled

          const amount =
            lastExchangeOrder.getLongOrShortSide() === ExchangeOrder.SIDE_LONG
              ? Math.abs(lastExchangeOrder.amount)
              : Math.abs(lastExchangeOrder.amount) * -1;

          // create a retry order with the order amount we had before; eg if partially filled
          const retryOrder =
            pairState.getState() === PairState.STATE_CLOSE
              ? Order.createCloseOrderWithPriceAdjustment(pairState.getSymbol(), amount)
              : Order.createLimitPostOnlyOrderAutoAdjustedPriceOrder(pairState.getSymbol(), amount);

          this.logger.error(`OrderAdjust: replacing canceled order: ${JSON.stringify(retryOrder)}`);

          const exchangeOrder = await this.executeOrder(pairState.getOrder(), retryOrder);
          pairState.setExchangeOrder(exchangeOrder);
        } else {
          this.logger.error(`OrderAdjust: Unknown order state: ${JSON.stringify([pairState, updatedOrder])}`);
        }
      } catch (err) {
        this.logger.error(`OrderAdjust: adjusted failed: ${JSON.stringify([String(err), pairState, orderUpdate])}`);
      }

      delete this.runningOrders[exchangeOrder.id];
    };

    return Promise.all(pairStates.map(pairState => visitExchangeOrder(pairState)));
  }
Keep open orders in orderbook at first position