/**
  * This method is mainly to cancel replace an order. We find the original order in the books, then
  * we renew its information. then we push it back to the financial.book as a new order.
  */
 public String cxrOrder(OrderCxRImpl changeOrder) {
   // get the id of the cancel replace order
   String orderID = changeOrder.getOrderId();
   // find the order in the financial.book
   NewOrderImpl renewOrder = lookUpOrder(orderID);
   // renew the order, then push it back into the financial.book as a new order
   String orderSymbol = renewOrder.getSymbol();
   if (renewOrder != null && changeOrder.getSize() != 0) {
     // renew the size of the order
     renewOrder.size = changeOrder.getSize();
     // renew the price of the order
     renewOrder.limitPrice = changeOrder.getLimitPrice();
     // get the bidbook and askbook of that certain symbol
     Hashtable<Double, LinkedList<NewOrderImpl>> tempbid =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     Hashtable<Double, LinkedList<NewOrderImpl>> tempask =
         new Hashtable<Double, LinkedList<NewOrderImpl>>();
     if (bid.containsKey(orderSymbol)) {
       tempbid = bid.get(orderSymbol);
     }
     if (ask.containsKey(orderSymbol)) {
       tempask = ask.get(orderSymbol);
     }
     // add the changed order back to the books.
     addNewOrder(renewOrder, orderSymbol, tempbid, tempask);
   }
   // return the symbol of the cancel and replace order.
   return orderSymbol;
 }
  /**
   * This method is mainly to add a new order into the certain bidbook or askbook , which
   * named @param myNewOrder the method returns nothing, but has side effect of changing that
   * bidbook or askbook. Once get a new order, first check it is a bid order or an ask order. If the
   * size of the order is positive, then it is a bid order, otherwise, it is a ask order. Then you
   * judge the price of the order. If the price shows Double.NaN,it means this is a marketprice
   * order, in another words, any price is okay for this order to make a deal. After that i make a
   * deal if the situation is allowed. If there is no trade can be done, then push the order into
   * the according financial.book.
   */
  public void addNewOrder(
      NewOrderImpl myNewOrder,
      String symbol,
      Hashtable<Double, LinkedList<NewOrderImpl>> bidbook,
      Hashtable<Double, LinkedList<NewOrderImpl>> askbook) {
    // myprice is a double, which is the limitprice of the input myNewOrder.
    double myprice = myNewOrder.getLimitPrice();
    // temp is a linkedlist with the object NewOrderImpl, which is intended to be used as the list
    // contains the orders which the new order could be traded with.
    LinkedList<NewOrderImpl> temp = new LinkedList<NewOrderImpl>();
    // to judge if myNewOrder is a bid order.
    if (myNewOrder.size >= 0) {
      // to judge if myNewOrder is with marketprice.
      if (myprice == Double.NaN) {

        // get the best ask price, named marketprice.
        Double marketprice = getLowestAsk(askbook);
        // get the ask orders in askbook which price the marketprice, also meaning these orders have
        // the priority to trade with the new order.
        LinkedList<NewOrderImpl> asktrade = askbook.get(marketprice);
        /**
         * The trade part As long as the new order with markerprice hasn't been traded all, we find
         * the ask orders with current best ask price to share its size. Like been written below, if
         * the size of the order we get first is smaller than the remaining size of the new order,
         * then done the trade, and decrease the size of the new order, and then find the next best
         * ask order to trade. if the size of the best ask order is larger than the remaining size
         * of the new order, then done the trade, and cut the share of the best ask order. If the
         * orders in asktrade is all be traded, but there is still some shares in new order, we get
         * the next best ask price, and get a new list of orders with that price. We recursively do
         * the steps above, until the new order is traded completely.
         */
        while (myNewOrder.size != 0) {
          if (asktrade != null) {
            NewOrderImpl firstOrder = asktrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              asktrade.removeFirst();
            }
          } else {
            marketprice = getHighestBid(bidbook);
            asktrade = bidbook.get(marketprice);
          }
        }
      }
      // if myNewOrder is with limitprice
      else {
        // get the current best ask price, which named marketprice
        Double marketprice = getLowestAsk(askbook);
        // to check if there is some ask orders can be traded with the new order right now, which
        // means the best ask price is smaller than the limit price of new order.
        if (marketprice <= myprice) {
          // build a new linked list to contain the orders with the best price to be traded with the
          // new order.
          LinkedList<NewOrderImpl> asktrade = new LinkedList<NewOrderImpl>();
          /**
           * The trade part As long as the new order with markerprice hasn't been traded all, we
           * find the ask orders with current best ask price to share its size. Like been written
           * below, if the size of the order we get first is smaller than the remaining size of the
           * new order, then done the trade, and decrease the size of the new order, and then find
           * the next best ask order to trade. if the size of the best ask order is larger than the
           * remaining size of the new order, then done the trade, and cut the share of the best ask
           * order. then we get the latest best ask price. We recursively do the steps above, unless
           * the new order's size come to zero or there is no ask order can be traded with the new
           * order.
           */
          while (myNewOrder.size != 0 && marketprice <= myprice) {
            asktrade = askbook.get(marketprice);
            NewOrderImpl firstOrder = asktrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              asktrade.removeFirst();
            }
            marketprice = getLowestAsk(askbook);
          }
          // if after the trade above, the new order is still not empty, then put it into the bid
          // financial.book.
          if (myNewOrder.size != 0) {
            if (bidbook.containsKey(myprice)) {
              temp = bidbook.get(myprice);
            }
            temp.push(myNewOrder);
            bidbook.put(myprice, temp);
          }
        }
        // if there is no order can be traded with the new order, just put it into the bid
        // financial.book.
        else {
          if (bidbook.containsKey(myprice)) {
            temp = bidbook.get(myprice);
          }
          temp.push(myNewOrder);
          bidbook.put(myprice, temp);
        }
      }
    }
    // if the new order is a ask order.
    else {
      // to judge if myNewOrder is with marketprice.
      if (myprice == Double.NaN) {

        // get the best bid price, named marketprice.
        Double marketprice = getHighestBid(bidbook);
        // get the bid orders in bidbook which price the marketprice, also meaning these orders have
        // the priority to trade with the new order.
        LinkedList<NewOrderImpl> bidtrade = bidbook.get(marketprice);
        /**
         * The trade part As long as the new order with markerprice hasn't been traded all, we find
         * the bid orders with current best bid price to share its size. Like been written below, if
         * the size of the order we get first is smaller than the remaining size of the new order,
         * then done the trade, and decrease the size of the new order. if the size of the best bid
         * order is larger than the remaining size of the new order, then done the trade, and cut
         * the share of the best bid order. If the orders in bidtrade is all be traded, but there is
         * still some shares in new order, we get the next best bid price, and get a new list of
         * orders with that price. We recursively do the steps above, until the new order is traded
         * completely.
         */
        while (myNewOrder.size != 0) {
          if (bidtrade != null) {
            NewOrderImpl firstOrder = bidtrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              bidtrade.removeFirst();
            }
          } else {
            marketprice = getHighestBid(bidbook);
            bidtrade = bidbook.get(marketprice);
          }
        }
      }
      // if myNewOrder is with limitprice
      else {
        // get the current best bid price, which named marketprice
        Double marketprice = getHighestBid(bidbook);
        // to check if there is some bid orders can be traded with the new order right now, which
        // means the best bid price is larger than the limit price of new order.
        if (marketprice >= myprice) {
          // build a new linked list to contain the orders with the best price to be traded with the
          // new order.
          LinkedList<NewOrderImpl> bidtrade = new LinkedList<NewOrderImpl>();
          /**
           * The trade part As long as the new order with markerprice hasn't been traded all, we
           * find the bid orders with current best bid price to share its size. Like been written
           * below, if the size of the order we get first is smaller than the remaining size of the
           * new order, then done the trade, and decrease the size of the new order. if the size of
           * the best bid order is larger than the remaining size of the new order, then done the
           * trade, and cut the share of the best bid order. then we get the latest best bid price.
           * We recursively do the steps above, unless the new order's size come to zero or there is
           * no bid order can be traded with the new order.
           */
          while (myNewOrder.size != 0 && marketprice >= myprice) {
            bidtrade = bidbook.get(marketprice);
            NewOrderImpl firstOrder = bidtrade.getFirst();
            if (Math.abs(firstOrder.size) > Math.abs(myNewOrder.size)) {
              firstOrder.size += myNewOrder.size;
              myNewOrder.size = 0;
            } else {
              myNewOrder.size += firstOrder.size;
              bidtrade.removeFirst();
            }
            marketprice = getHighestBid(bidbook);
          }
          // if after the trade above, the new order is still not empty, then put it into the ask
          // financial.book.
          if (myNewOrder.size != 0) {
            if (askbook.containsKey(myprice)) {
              temp = askbook.get(myprice);
            }
            temp.push(myNewOrder);
            askbook.put(myprice, temp);
          }
        }
        // if there is no order can be traded with the new order, just put it into the ask
        // financial.book.
        else {
          if (askbook.containsKey(myprice)) {
            temp = askbook.get(myprice);
          }
          temp.push(myNewOrder);
          askbook.put(myprice, temp);
        }
      }
    }
    bid.put(symbol, bidbook);
    ask.put(symbol, askbook);
  }