Example #1
0
        private void CTPOnRtnTrade(ref CThostFtdcTradeField pTrade)
        {
            if (!IsLogin)
            {
                _rtnOrderTime = DateTime.Now;
            }

            string     id;
            OrderField of = null;

            if (!(_dicSysidSfrId.TryGetValue(pTrade.OrderSysID, out id) && DicOrderField.TryGetValue(id, out of)))
            {
                CThostFtdcTradeField fReTrade = pTrade;
                var list = _sysidTrade.GetOrAdd(pTrade.OrderSysID, new List <CThostFtdcTradeField>());
                list.Add(fReTrade);
                return;
            }

            TradeField f = new TradeField
            {
                Hedge = pTrade.HedgeFlag == TThostFtdcHedgeFlagType.THOST_FTDC_HF_Speculation ? HedgeType.Speculation
                                        : pTrade.HedgeFlag == TThostFtdcHedgeFlagType.THOST_FTDC_HF_Arbitrage ? HedgeType.Arbitrage : HedgeType.Hedge,
                Direction = pTrade.Direction == TThostFtdcDirectionType.THOST_FTDC_D_Buy ? DirectionType.Buy : DirectionType.Sell,

                //ExchangeID = pTrade.ExchangeID,
                InstrumentID = pTrade.InstrumentID,
                Offset       = pTrade.OffsetFlag == TThostFtdcOffsetFlagType.THOST_FTDC_OF_Open ? OffsetType.Open
                                        : pTrade.OffsetFlag == TThostFtdcOffsetFlagType.THOST_FTDC_OF_CloseToday ? OffsetType.CloseToday : OffsetType.Close,
                Price      = pTrade.Price,
                TradeID    = pTrade.TradeID + (char)pTrade.Direction,
                TradeTime  = pTrade.TradeTime,
                TradingDay = pTrade.TradingDay,
                Volume     = pTrade.Volume,
                SysID      = pTrade.OrderSysID,
            };
            Exchange exc;

            if (Enum.TryParse(pTrade.ExchangeID, out exc))
            {
                f.ExchangeID = exc;
            }
            if (DicTradeField.TryAdd(f.TradeID, f)) // string.Format("{0}_{1}", f.TradeID, f.Direction), f))
            {
                f.OrderID      = id;                //更新成交对应的委托ID
                of.TradeTime   = pTrade.TradeTime;
                of.AvgPrice    = (of.AvgPrice * (of.Volume - of.VolumeLeft) + pTrade.Price * pTrade.Volume) / (of.Volume - of.VolumeLeft + pTrade.Volume);
                of.TradeVolume = pTrade.Volume;
                of.VolumeLeft -= of.TradeVolume;
                if (of.VolumeLeft == 0)
                {
                    of.Status    = OrderStatus.Filled;
                    of.StatusMsg = "全部成交";
                }
                else
                {
                    of.Status    = OrderStatus.Partial;
                    of.StatusMsg = "部分成交";
                }

                if (IsLogin)
                {
                    #region 更新持仓
                    PositionField pf;
                    //处理持仓
                    if (f.Offset == OffsetType.Open)
                    {
                        pf = DicPositionField.GetOrAdd(f.InstrumentID + "_" + f.Direction, new PositionField());
                        pf.InstrumentID = f.InstrumentID;
                        pf.Direction    = f.Direction;
                        pf.Hedge        = f.Hedge;
                        pf.Price        = (pf.Price * pf.Position + f.Price * f.Volume) / (pf.Position + f.Volume);
                        pf.TdPosition  += f.Volume;
                        pf.Position    += f.Volume;
                    }
                    else
                    {
                        pf = this.DicPositionField.GetOrAdd(f.InstrumentID + "_" + (f.Direction == DirectionType.Buy ? "Sell" : "Buy"), new PositionField());
                        if (f.Offset == OffsetType.CloseToday)
                        {
                            pf.TdPosition -= f.Volume;
                        }
                        else
                        {
                            int tdClose = Math.Min(pf.TdPosition, f.Volume);
                            if (pf.TdPosition > 0)
                            {
                                pf.TdPosition -= tdClose;
                            }
                            pf.YdPosition -= Math.Max(0, f.Volume - tdClose);
                        }
                        pf.Position -= f.Volume;
                    }
                    #endregion

                    //委托响应
                    _OnRtnOrder?.Invoke(this, new OrderArgs {
                        Value = of
                    });
                    //成交响应
                    _OnRtnTrade?.Invoke(this, new TradeArgs {
                        Value = f
                    });
                }
            }
        }
Example #2
0
        private void CTPOnRtnOrder(ref CThostFtdcOrderField pOrder)
        {
            TimeSpan ts;

            if (!IsLogin)
            {
                _rtnOrderTime = DateTime.Now;                   //登录前接收所有旧的 order
            }
            if (string.IsNullOrEmpty(pOrder.InstrumentID))
            {
                return;
            }

            string id = string.Format("{0}|{1}|{2}", pOrder.SessionID, pOrder.FrontID, pOrder.OrderRef);
            //_dicLocalidSfrId.TryAdd(pOrder.OrderLocalID, id);//防止因此项未赋值,导致成交响应里无法更新

            long tmp;

            if (DicOrderField.TryAdd(id, new OrderField
            {
                Custom = (int)(long.TryParse(pOrder.OrderRef, out tmp) ? tmp % 1000000 : 0),
                //修复: 值为null会导致界面显示错误
                InsertTime = string.IsNullOrEmpty(pOrder.InsertTime) ? DateTime.Now.ToString("HH:mm:ss") : pOrder.InsertTime,
                InstrumentID = pOrder.InstrumentID,
                //SysID = string.Empty,        //为null会导致界面显示错误
                //TradeTime = string.Empty,

                IsLocal = pOrder.SessionID == _session,
                LimitPrice = pOrder.LimitPrice,
                OrderID = id,
                Volume = pOrder.VolumeTotalOriginal,
                VolumeLeft = pOrder.VolumeTotalOriginal,                 // pOrder->VolumeTotal;
                //f->VolumeLeft = pOrder->VolumeTotal; //由ontrade处理
                Status = OrderStatus.Normal,
                StatusMsg = pOrder.StatusMsg,
                Direction = pOrder.Direction == TThostFtdcDirectionType.THOST_FTDC_D_Buy ? DirectionType.Buy : DirectionType.Sell,
                Hedge = (TThostFtdcHedgeFlagType)pOrder.CombHedgeFlag[0] == TThostFtdcHedgeFlagType.THOST_FTDC_HF_Speculation ? HedgeType.Speculation : (TThostFtdcHedgeFlagType)pOrder.CombHedgeFlag[0] == TThostFtdcHedgeFlagType.THOST_FTDC_HF_Arbitrage ? HedgeType.Arbitrage : HedgeType.Hedge,
                Offset = (TThostFtdcOffsetFlagType)pOrder.CombOffsetFlag[0] == TThostFtdcOffsetFlagType.THOST_FTDC_OF_Open ? OffsetType.Open : (TThostFtdcOffsetFlagType)pOrder.CombOffsetFlag[0] == TThostFtdcOffsetFlagType.THOST_FTDC_OF_CloseToday ? OffsetType.CloseToday : OffsetType.Close,
            }))             //首次响应
            {
                //if (pOrder.OrderLocalID.Length > 0) //成交响应时用
                if (IsLogin)
                {
                    _OnRtnOrder?.Invoke(this, new OrderArgs {
                        Value = DicOrderField[id]
                    });
                }
            }
            else
            {
                OrderField f = DicOrderField[id];
                //修复: 值为null会导致界面显示错误
                f.InsertTime = string.IsNullOrEmpty(pOrder.InsertTime) ? DateTime.Now.ToString("HH:mm:ss") : pOrder.InsertTime;

                if (_excTime == DateTime.MinValue && TimeSpan.TryParse(f.InsertTime, out ts))                 //首次的onrtnorder时间有问题,故放在此处更新_exctime
                {
                    _excTime = DateTime.Today.Add(ts);
                    _sw.Restart();
                }

                if (TThostFtdcOrderStatusType.THOST_FTDC_OST_Canceled == pOrder.OrderStatus)
                {
                    f.Status    = OrderStatus.Canceled;
                    f.StatusMsg = pOrder.StatusMsg;
                    if (!string.IsNullOrEmpty(pOrder.CancelTime))
                    {
                        f.TradeTime = pOrder.CancelTime;
                    }
                    else if (IsLogin)                    //成撤时间:此处为撤单时间
                    {
                        f.TradeTime = DateTime.Now.ToString("HH:mm:ss");
                    }

                    if (IsLogin)
                    {
                        //委托被拒绝的撤单按错误处理
                        if (pOrder.StatusMsg.IndexOf(@"被拒绝") >= 0)
                        {
                            _OnRtnErrOrder?.Invoke(this, new ErrOrderArgs {
                                ErrorID = -1, ErrorMsg = pOrder.StatusMsg, Value = f
                            });
                        }
                        else
                        {
                            _OnRtnCancel?.Invoke(this, new OrderArgs {
                                Value = f,
                            });
                        }
                    }
                    //撤单次数等规则由业务层处理
                    //_dicCancelTimes.AddOrUpdate(f.InstrumentID, 1, (k, v) => v + 1);
                    //if (_dicCancelTimes[f.InstrumentID] >= 450 && _dicCancelTimes[f.InstrumentID] % 10 == 0)
                    //{
                    //	if (IsLogin && _caller._OnRtnErrCancel != null)
                    //		_caller._OnRtnErrOrder(_caller, new ErrOrderArgs
                    //		{
                    //			ErrorID = -1,
                    //			ErrorMsg = string.Format("撤单次数将要达到上限500次[{0}]", _dicCancelTimes[f.InstrumentID]),
                    //			Value = f,
                    //		});
                    //}
                }
            }

            //委托到交易所
            if (!string.IsNullOrEmpty(pOrder.OrderSysID))
            {
                DicOrderField[id].SysID = pOrder.OrderSysID;

                if (_dicSysidSfrId.TryAdd(pOrder.OrderSysID, id))
                {
                    List <CThostFtdcTradeField> list;
                    //成交先至,则在此处再调成交
                    if (_sysidTrade.TryGetValue(pOrder.OrderSysID, out list))
                    {
                        foreach (CThostFtdcTradeField t1 in list)
                        {
                            var t = t1;
                            //再调用rtntrade: 成交响应在rtntrade中完成
                            CTPOnRtnTrade(ref t);
                        }
                        list.Clear();
                    }
                }
            }
        }