Esempio n. 1
0
        public void OrderFilledEvent(List <Fill> FillList)
        {
            var   fillDetails = FillList.FirstOrDefault();
            Int32 orderIndex  = -1;

            try
            {
                orderIndex = FillWatchList.FindIndex((o) => o.OrderId == fillDetails.OrderId);
            }
            catch (Exception)
            {
                Logger.WriteLog(string.Format("Order {0} not found in watch list!", fillDetails.OrderId));
                return;
            }

            decimal totalFilled = 0;


            //test
            //var testFill = FillList.First();//new Fill(null);
            //testFill = FillList.First();
            ////testFill.
            //FillList.Add(testFill);



            //reset the filled size assuming all the split orders are retunred
            if (FillList.Count > 0)
            {
                FillWatchList[orderIndex].FilledSize = 0.00m;
                foreach (var curFill in FillList)
                {
                    totalFilled += Convert.ToDecimal(curFill.Size);
                    FillWatchList[orderIndex].FilledSize = FillWatchList[orderIndex].FilledSize
                                                           + Convert.ToDecimal(curFill.Size);
                }
            }
            else
            {
                //error condition where there is no data in filled order
                return;
            }



            //check if ordered size and fill size match,
            //if it does then remove from watch list
            //else mark it was partially filled

            var majorityFillSize = FillWatchList[orderIndex].ProductSize * 1; //0.99m;

            if (FillWatchList[orderIndex].FilledSize == majorityFillSize)     //if filled size is more than 90%
            {
                //BusyCheckingOrder = false;
                //myActiveOrderBook.RemoveFromOrderList(fillDetails.OrderId);



                Logger.WriteLog("Order filled with following sizes:");
                FillList.ForEach((f) => Logger.WriteLog(f.Size + " @" + f.Price + " (fee: " + f.Fee + ")"));

                //add the list of filled sizes to fill list if the filledList does not already contain it
                foreach (var f in FillList)
                {
                    if (!(FillWatchList[orderIndex].FilledList.Any((e) => e.OrderId == f.OrderId && e.Side == f.Side && e.Fee == f.Fee))) //if list does not already contain item then add
                    {
                        FillWatchList[orderIndex].FilledList.Add(f);
                    }
                }

                //blindly adds all filled even if already exists in list
                //FillWatchList[orderIndex].FilledList.AddRange(FillList);

                if (fillDetails.Price == null) //indicates a market order
                {
                    try
                    {
                        var orderStat = GetFillStatus(fillDetails?.OrderId).Result;
                        if (orderStat.Fills.Count > 0)
                        {
                            fillDetails.Price = orderStat.Fills.FirstOrDefault().Price;
                        }
                    }
                    catch (Exception)
                    {
                        Logger.WriteLog("Error getting fill response");
                    }
                }


                var filledSizeSum    = 0.0m;
                var filledAmountSum  = 0.0m;
                var filledFeeSum     = 0.0m;
                var filledAtAvgPrice = 0.0m;

                Logger.WriteLog("All fills:");
                foreach (var fillDet in FillWatchList[orderIndex].FilledList)
                {
                    filledSizeSum   += Convert.ToDecimal(fillDet.Size);
                    filledAmountSum += Convert.ToDecimal(fillDet.Size) * Convert.ToDecimal(fillDet.Price);
                    filledFeeSum    += Convert.ToDecimal(fillDet.Fee);
                    Logger.WriteLog(fillDet.Size + " @" + fillDet.Price + " (fee: " + fillDet.Fee + ")");
                }

                if (filledSizeSum > 0)
                {
                    filledAtAvgPrice = filledAmountSum / filledSizeSum;
                }

                //fillDetails.Size = totalFilled.ToString();
                fillDetails.Size  = filledSizeSum.ToString();
                fillDetails.Price = filledAtAvgPrice.ToString();
                fillDetails.Fee   = filledFeeSum.ToString();

                FillWatchList.RemoveAll(x => x.OrderId == fillDetails.OrderId);
                FillUpdated?.Invoke(this, new FillEventArgs {
                    filledOrder = fillDetails
                });
            }
            else
            {
                //cancel the order here the first time and retry to fill unfilled amount in OrderBook

                var myCurrentOrder = FillWatchList[orderIndex];

                //when checking the same order after the first time
                //if not (partially filled or Cancel_error)
                //skip if market order
                if (!(FillWatchList[orderIndex].Status == "PARTIALLY_FILLED" ||
                      FillWatchList[orderIndex].Status == "CANCEL_ERROR" ||
                      FillWatchList[orderIndex].OrderType == "market"))
                {
                    ////add the list of filled sizes to fill list
                    //FillWatchList[orderIndex].FilledList.AddRange(FillList);

                    //add the list of filled sizes to fill list if the filledList does not already contain it
                    foreach (var f in FillList)
                    {
                        if (!(FillWatchList[orderIndex].FilledList.Any((e) => e.OrderId == f.OrderId && e.Side == f.Side && e.Fee == f.Fee))) //if list does not already contain item then add
                        {
                            FillWatchList[orderIndex].FilledList.Add(f);
                        }
                    }


                    Logger.WriteLog(string.Format("{0} order({1}) of {2} {3} filled partially with following sizes:",
                                                  fillDetails.Side, fillDetails.OrderId, FillWatchList[orderIndex].ProductSize,
                                                  fillDetails.ProductId));

                    FillList.ForEach((f) => Logger.WriteLog(f.Size + " @" + f.Price + " (fee: " + f.Fee + ")"));

                    try
                    {
                        Logger.WriteLog("Cancelling remainder of partially filled order: " + myCurrentOrder.OrderId);


                        if (myCurrentOrder.OrderType == "market")
                        {
                            Logger.WriteLog("market order! cant cancel");
                        }
                        var cancelledOrder = myActiveOrderBook.CancelSingleOrder(myCurrentOrder.OrderId).Result;
                        if (cancelledOrder.Count > 0)
                        {
                            FillWatchList[orderIndex].Status = "PARTIALLY_FILLED";
                        }
                    }
                    catch (Exception)
                    {
                        Logger.WriteLog("Error cancelling partially filled order, marking as CANCEL_ERROR " + myCurrentOrder.OrderId);
                        // this will stop from entering this method
                        //also it will be tried to be cancelled in cancelAndReorder where
                        //it will fail and a new order will be placed
                        FillWatchList[orderIndex].Status = "CANCEL_ERROR";
                    }
                }

                //set the current order in the list to partially filled
                //FillWatchList[orderIndex].Status = "PARTIALLY_FILLED";
            }


            //fillDetails.Size = totalFilled.ToString(); //modify the filled size with the total instead of the first size in list

            //BusyCheckingOrder = false;

            //notify only if fully filled?
            //FillUpdated?.Invoke(this, new FillEventArgs { filledOrder = fillDetails });
        }