private void AddActiveStoplossOrder(StoplossOrder order)
        {
            if (!_activeOrders.ContainsKey(order.SecurityCode))
            {
                _activeOrders.Add(order.SecurityCode, new List <StoplossOrder>());
            }

            _activeOrders[order.SecurityCode].Add(order);
        }
        private void OnOrderStatusChanged(DispatchedOrder dispatchedOrder)
        {
            if (dispatchedOrder == null)
            {
                return;
            }

            if (dispatchedOrder.Request.AssociatedObject != null)
            {
                StoplossOrder order = dispatchedOrder.Request.AssociatedObject as StoplossOrder;

                if (order == null)
                {
                    return;
                }

                if (TradingHelper.IsFinalStatus(dispatchedOrder.LastStatus))
                {
                    lock (_orderLockObj)
                    {
                        if (!IsSentOrder(order))
                        {
                            return;
                        }

                        ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                        if (logger != null)
                        {
                            logger.InfoFormat(
                                "Stoploss order executed:  id {0} code {1} status {2} suceeded volume {3}.",
                                order.OrderId,
                                order.SecurityCode,
                                dispatchedOrder.LastStatus,
                                dispatchedOrder.SucceededVolume);
                        }

                        order.UpdateExistingVolume(dispatchedOrder.SucceededVolume);

                        RemoveSentOrder(order);

                        if (order.ExistingVolume > 0)
                        {
                            // the order has not been finished yet, put it back into active order
                            AddActiveStoplossOrder(order);

                            if (TradingHelper.IsSucceededFinalStatus(dispatchedOrder.LastStatus))
                            {
                                // send out order again
                                SendStoplossOrder(order);
                            }
                        }
                    }
                }
            }
        }
        private void SendStoplossOrderWorkItem(object state)
        {
            StoplossOrder order = (StoplossOrder)state;

            OrderRequest request = new OrderRequest(order)
            {
                Category     = OrderCategory.Sell,
                Price        = order.StoplossPrice,
                PricingType  = OrderPricingType.MakertPriceMakeDealInFiveGradesThenCancel,
                Volume       = order.ExistingVolume,
                SecurityCode = order.SecurityCode,
            };

            string          error;
            DispatchedOrder dispatchedOrder = CtpSimulator.GetInstance().DispatchOrder(request, out error);

            if (dispatchedOrder == null)
            {
                ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                if (logger != null)
                {
                    logger.ErrorFormat(
                        "Exception in dispatching stop loss order: id {0} code {1} stoploss price {2}, volume {3}. Error: {4}",
                        order.OrderId,
                        order.SecurityCode,
                        order.StoplossPrice,
                        order.ExistingVolume,
                        error);
                }
            }
            else
            {
                ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                if (logger != null)
                {
                    logger.InfoFormat(
                        "Dispatched stop loss order: id {0} code {1} stoploss price {2}, volume {3}.",
                        order.OrderId,
                        order.SecurityCode,
                        order.StoplossPrice,
                        order.ExistingVolume);
                }

                lock (_orderLockObj)
                {
                    RemoveActiveStoplossOrder(order);
                    AddSentOrder(order);
                }

                // force query order status.
                CtpSimulator.GetInstance().QueryOrderStatusForcibly();
            }
        }
        public void RegisterStoplossOrder(StoplossOrder order)
        {
            if (order == null)
            {
                throw new ArgumentNullException();
            }

            lock (_orderLockObj)
            {
                AddActiveStoplossOrder(order);
            }

            CtpSimulator.GetInstance().SubscribeQuote(order.SecurityCode);
        }
        private bool RemoveActiveStoplossOrder(StoplossOrder order)
        {
            List <StoplossOrder> orders;

            if (!_activeOrders.TryGetValue(order.SecurityCode, out orders))
            {
                return(false);
            }

            bool removeSucceeded = orders.Remove(order);

            if (orders.Count == 0)
            {
                _activeOrders.Remove(order.SecurityCode);
            }

            return(removeSucceeded);
        }
        private bool ShouldStoploss(FiveLevelQuote quote, float maxBuyPrice, float minBuyPrice, int totalBuyVolume, StoplossOrder order)
        {
            bool shouldStoploss = false;

            if (order.StoplossPrice < minBuyPrice)
            {
                if (totalBuyVolume > order.ExistingVolume)
                {
                }
                else
                {
                    // no solution yet, need to predicate volume.
                    // TODO: predicate volume
                }
            }
            else
            {
                if (order.StoplossPrice >= maxBuyPrice)
                {
                    // need to stop loss immediately.
                    shouldStoploss = true;
                }
                else
                {
                    // order stop loss price is between minBuyPrice and maxBuyPrice
                    // we count the buy volume above stop loss price.
                    int aboveStoplossBuyVolume =
                        ChinaStockHelper.ConvertHandToVolume(
                            Enumerable
                            .Range(0, quote.BuyPrices.Length)
                            .Where(index => quote.BuyPrices[index] >= order.StoplossPrice)
                            .Sum(index => quote.BuyVolumesInHand[index]));

                    if (aboveStoplossBuyVolume <= order.ExistingVolume * 5)
                    {
                        shouldStoploss = true;
                    }
                    else
                    {
                        // there is enough buy volume now, so don't be rush.
                    }
                }
            }

            return(shouldStoploss);
        }
 private bool IsSentOrder(StoplossOrder order)
 {
     return(_sentOrders.Contains(order));
 }
 private bool RemoveSentOrder(StoplossOrder order)
 {
     return(_sentOrders.Remove(order));
 }
 private void AddSentOrder(StoplossOrder order)
 {
     _sentOrders.Add(order);
 }
 private void SendStoplossOrder(StoplossOrder order)
 {
     // put it into thread pool to avoid recursively call QueryOrderStatusForcibly and
     // then call OnOrderStatusChanged() and then call SendStoplossOrder recursively.
     ThreadPool.QueueUserWorkItem(SendStoplossOrderWorkItem, order);
 }