/// <summary> /// CTP InstrumentField To USeInstrumentDetail。 /// </summary> /// <param name="filed"></param> /// <returns></returns> private USeInstrumentDetail CtpInstrumentFieldToUSeInstrumentDetail(InstrumentField filed) { USeMarket market = CtpProtocol.FtdcExchangeToUSeMarket(filed.ExchangeID); Debug.Assert(market != USeMarket.Unknown, "CtpInstrumentFieldToUSeInstrumentDetail(),market is unknown."); USeInstrumentDetail detail = new USeInstrumentDetail(); detail.Instrument = new USeInstrument(filed.InstrumentID, filed.InstrumentName, market); try { detail.OpenDate = DateTime.ParseExact(filed.OpenDate, "yyyyMMdd", null); detail.ExpireDate = DateTime.ParseExact(filed.ExpireDate, "yyyyMMdd", null); if (string.IsNullOrEmpty(filed.StartDelivDate) == false) { detail.StartDelivDate = DateTime.ParseExact(filed.StartDelivDate, "yyyyMMdd", null); } else { //[yangming] 有的合约查询不到开始交割日,暂时用到期日下一天 detail.StartDelivDate = detail.ExpireDate.AddDays(1); } detail.EndDelivDate = DateTime.ParseExact(filed.EndDelivDate, "yyyyMMdd", null); detail.VolumeMultiple = filed.VolumeMultiple; detail.IsTrading = filed.IsTrading == IntBoolType.Yes; detail.Varieties = filed.ProductID; detail.PriceTick = filed.PriceTick.ToDecimal(); detail.ExchangeLongMarginRatio = filed.LongMarginRatio.ToDecimal(); detail.ExchangeShortMarginRatio = filed.ShortMarginRatio.ToDecimal(); detail.MaxMarketOrderVolume = filed.MaxMarketOrderVolume; detail.MinMarketOrderVolume = filed.MinMarketOrderVolume; detail.MaxLimitOrderVolume = filed.MaxLimitOrderVolume; detail.MinLimitOrderVolume = filed.MinLimitOrderVolume; } catch (Exception ex) { Debug.Assert(false, "CtpInstrumentFieldToUSeInstrumentDetail() convet failed," + ex.Message); } return(detail); }
/// <summary> /// 委托下单。 /// </summary> /// <param name="instrument">委托产品。</param> /// <param name="qty">委托量。</param> /// <param name="price">委托价格。</param> /// <param name="offsetType">开平仓方向。</param> /// <param name="orderSide">买卖方向。</param> /// <param name="error">[out]委托失败原因。</param> /// <returns>委托单号。</returns> /// <remarks>返回为null代表失败,否则为委托单号。</remarks> public override USeOrderNum PlaceOrder(USeInstrument instrument, int qty, decimal price, USeOffsetType offsetType, USeOrderSide orderSide, out string error) { if (m_ctpUser == null || m_ctpUser.IsLogin == false) { error = "OrderServer unable"; return(null); } string orderRef = m_orderRefIDCreator.Next().ToString(); // 生成报单引用 int requestID = m_requetSeqIDCreator.Next(); error = string.Empty; try { OffsetFlagType ctpOffsetFlag; switch (offsetType) { case USeOffsetType.Open: ctpOffsetFlag = OffsetFlagType.Open; break; case USeOffsetType.Close: ctpOffsetFlag = OffsetFlagType.Close; break; case USeOffsetType.CloseToday: ctpOffsetFlag = OffsetFlagType.CloseToday; break; case USeOffsetType.CloseHistory: ctpOffsetFlag = OffsetFlagType.CloseYesterday; break; default: throw new ArgumentException(string.Format("Invalid offsetType {0}.", offsetType), "offsetType"); } DirectionType ctpDirection; switch (orderSide) { case USeOrderSide.Buy: ctpDirection = DirectionType.Buy; break; case USeOrderSide.Sell: ctpDirection = DirectionType.Sell; break; default: throw new ArgumentException(string.Format("Invalid orderside {0}.", orderSide), "orderSide"); } InputOrderField requestField = new InputOrderField(); requestField.BrokerID = m_brokerID; requestField.InvestorID = m_investorID; requestField.InstrumentID = instrument.InstrumentCode; requestField.OrderRef = orderRef; requestField.UserID = m_investorID; requestField.OrderPriceType = OrderPriceType.LimitPrice; requestField.Direction = ctpDirection; requestField.CombOffsetFlag1 = ctpOffsetFlag; requestField.CombHedgeFlag1 = HedgeFlagType.Speculation; requestField.LimitPrice = Convert.ToDouble(price); requestField.VolumeTotalOriginal = qty; requestField.TimeCondition = TimeConditionType.GFD; requestField.VolumeCondition = VolumeConditionType.AV; requestField.MinVolume = 1; requestField.ContingentCondition = ContingentConditionType.Immediately; requestField.ForceCloseReason = ForceCloseReasonType.NotForceClose; requestField.IsAutoSuspend = IntBoolType.No; requestField.BusinessUnit = null; requestField.RequestID = requestID; requestField.UserForceClose = IntBoolType.No; //构造一个委托回报,防止报单不合规等问题遭CTP拒绝,但未有委托回报推送 OrderField orderField = new OrderField(); orderField.BrokerID = m_brokerID; orderField.FrontID = m_frontID; orderField.SessionID = m_sessionID; orderField.OrderRef = orderRef; orderField.OrderSysID = string.Empty; orderField.InvestorID = m_investorID; orderField.InstrumentID = instrument.InstrumentCode; orderField.ExchangeID = CtpProtocol.USeMarketToFtdcExchange(instrument.Market); orderField.VolumeTotalOriginal = qty; orderField.LimitPrice = Convert.ToDouble(price); orderField.VolumeTraded = 0; orderField.OrderStatus = OrderStatusType.Unknown; orderField.Direction = orderSide == USeOrderSide.Buy ? DirectionType.Buy : DirectionType.Sell; switch (offsetType) { case USeOffsetType.Open: orderField.CombOffsetFlag1 = OffsetFlagType.Open; break; case USeOffsetType.Close: orderField.CombOffsetFlag1 = OffsetFlagType.Close; break; case USeOffsetType.CloseHistory: orderField.CombOffsetFlag1 = OffsetFlagType.CloseYesterday; break; case USeOffsetType.CloseToday: orderField.CombOffsetFlag1 = OffsetFlagType.CloseToday; break; } orderField.InsertDate = DateTime.Now.ToString("yyyyMMdd"); orderField.InsertTime = DateTime.Now.ToString("HH:mm:ss"); m_dataBuffer.UpdateOrderField(orderField); m_ctpUser.ReqOrderInsert(ref requestField, requestID); USeOrderNum orderNum = new CtpOrderNum(m_frontID, m_sessionID, orderRef); m_logger.WriteInformation(string.Format("{0}.PlaceOrder() ok,[RequestID:{1}][Instrument:{2}][FulcOffsetType{3}][Qty:{4}][Price:{5}].", ToString(), requestID, instrument.InstrumentCode, offsetType, qty, price)); return(orderNum); } catch (Exception ex) { m_logger.WriteError(string.Format("{0} placeorder[Instrument:{1}][FulcOffsetType:{2}][Qty:{3}][Price:{4}] failed,Error:{5}.", ToString(), instrument.InstrumentCode, offsetType, qty, price, ex.Message)); error = ex.Message; return(null); } }
/// <summary> /// CTP OrderField To USeOrderBook。 /// </summary> /// <param name="field"></param> /// <returns></returns> private USeOrderBook CtpOrderFieldToUSeOrderBook(OrderField field) { USeOrderBook orderbook = new USeOrderBook(); try { orderbook.OrderNum = new CtpOrderNum(field.FrontID, field.SessionID, field.OrderRef, field.ExchangeID, field.OrderSysID); orderbook.Account = field.InvestorID.ToString().Trim(); orderbook.Instrument = new USeInstrument(field.InstrumentID.Trim(), field.InstrumentID.Trim(), CtpProtocol.FtdcExchangeToUSeMarket(field.ExchangeID)); orderbook.OrderQty = field.VolumeTotalOriginal; orderbook.OrderPrice = Convert.ToDecimal(field.LimitPrice); orderbook.TradeQty = field.VolumeTraded; orderbook.TradeAmount = 0m; // 此处转换不处理,最终再计算 switch (field.OrderStatus) { case OrderStatusType.AllTraded: orderbook.OrderStatus = USeOrderStatus.AllTraded; break; case OrderStatusType.PartTradedNotQueueing: case OrderStatusType.PartTradedQueueing: orderbook.OrderStatus = USeOrderStatus.PartTraded; break; case OrderStatusType.Canceled: orderbook.OrderStatus = field.VolumeTraded > 0 ? USeOrderStatus.PartCanceled : USeOrderStatus.AllCanceled; break; case OrderStatusType.NoTradeQueueing: case OrderStatusType.NoTradeNotQueueing: orderbook.OrderStatus = USeOrderStatus.NoTraded; break; case OrderStatusType.Unknown: orderbook.OrderStatus = USeOrderStatus.Unknown; break; default: { Debug.Assert(false, string.Format("CtpOrderFieldToUSeOrderBook() unknown OrderStatus [{0}]", field.OrderStatus)); orderbook.OrderStatus = USeOrderStatus.Unknown; break; } } orderbook.CancelQty = field.OrderStatus == OrderStatusType.Canceled ? field.VolumeTotalOriginal - field.VolumeTraded : 0; orderbook.OrderSide = field.Direction == DirectionType.Buy ? USeOrderSide.Buy : USeOrderSide.Sell; switch (field.CombOffsetFlag1) { case OffsetFlagType.Close: case OffsetFlagType.ForceClose: orderbook.OffsetType = USeOffsetType.Close; break; case OffsetFlagType.CloseToday: orderbook.OffsetType = USeOffsetType.CloseToday; break; case OffsetFlagType.CloseYesterday: orderbook.OffsetType = USeOffsetType.CloseHistory; break; case OffsetFlagType.Open: orderbook.OffsetType = USeOffsetType.Open; break; default: Debug.Assert(false, "Invalid comb offset Flag1."); break; } orderbook.Memo = field.StatusMsg; DateTime orderTime = DateTime.Now; if (string.IsNullOrEmpty(field.InsertDate) && string.IsNullOrEmpty(field.InsertTime)) { Debug.Assert(false); orderTime = DateTime.Now; } else if (string.IsNullOrEmpty(field.InsertDate)) { if (DateTime.TryParseExact(DateTime.Today.ToString("yyyyMMdd") + field.InsertTime, "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out orderTime) == false) { Debug.Assert(false); orderTime = DateTime.Now; } } else { if (DateTime.TryParseExact(field.InsertDate + field.InsertTime, "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out orderTime) == false) { Debug.Assert(false); orderTime = DateTime.Now; } } orderbook.OrderTime = orderTime; } catch (Exception ex) { Debug.Assert(false, "CtpOrderFieldToUSeOrderBook() convet failed," + ex.Message); } return(orderbook); }
/// <summary> /// CTP TradeField To USeTradeBook。 /// </summary> /// <param name="field"></param> /// <returns></returns> private USeTradeBook CtpTradeFieldToUSeTradeBook(TradeField field) { USeTradeBook tradeBook = new USeTradeBook(); try { tradeBook.Instrument = new USeInstrument(field.InstrumentID.Trim(), field.InstrumentID.Trim(), CtpProtocol.FtdcExchangeToUSeMarket(field.ExchangeID)); tradeBook.TradeNum = field.TradeID.Trim(); USeOrderNum orderNum = new CtpOrderNum(field.ExchangeID, field.OrderSysID); USeOrderBook orderBook = m_dataBuffer.GetOrderBook(orderNum); if (orderBook != null) { orderNum = orderBook.OrderNum.Clone(); // 去搜索对应委托单,若存在则将委托单号设置为完整委托单号 } tradeBook.OrderNum = orderNum; tradeBook.OrderSide = field.Direction == DirectionType.Buy ? USeOrderSide.Buy : USeOrderSide.Sell; switch (field.OffsetFlag) { case OffsetFlagType.Close: case OffsetFlagType.ForceClose: tradeBook.OffsetType = USeOffsetType.Close; break; case OffsetFlagType.CloseToday: tradeBook.OffsetType = USeOffsetType.CloseToday; break; case OffsetFlagType.CloseYesterday: tradeBook.OffsetType = USeOffsetType.CloseHistory; break; case OffsetFlagType.Open: tradeBook.OffsetType = USeOffsetType.Open; break; default: Debug.Assert(false, string.Format("CtpTradeFieldToUSeTradeBook(),Invalid offsetfalg.", field.OffsetFlag)); break; } tradeBook.Price = Convert.ToDecimal(field.Price); tradeBook.Qty = field.Volume; tradeBook.Account = field.InvestorID; DateTime tradeTime = DateTime.Now; if (string.IsNullOrEmpty(field.TradeDate) && string.IsNullOrEmpty(field.TradeTime)) { Debug.Assert(false); tradeTime = DateTime.Now; } else if (string.IsNullOrEmpty(field.TradeDate)) { if (DateTime.TryParseExact(DateTime.Today.ToString("yyyyMMdd") + field.TradeTime, "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out tradeTime) == false) { Debug.Assert(false); tradeTime = DateTime.Now; } } else { if (DateTime.TryParseExact(field.TradeDate + field.TradeTime, "yyyyMMddHH:mm:ss", null, System.Globalization.DateTimeStyles.None, out tradeTime) == false) { Debug.Assert(false); tradeTime = DateTime.Now; } } tradeBook.TradeTime = tradeTime; int volumeMultiple = m_dataBuffer.GetVolumeMultiple(tradeBook.Instrument); tradeBook.Amount = tradeBook.Price * tradeBook.Qty * volumeMultiple; // 手续费尝试计算 tradeBook.Fee = m_dataBuffer.CalculateFee(tradeBook.Instrument, tradeBook.OffsetType, tradeBook.Qty, tradeBook.Price); } catch (Exception ex) { Debug.Assert(false, "CtpTradeFieldToUSeTradeBook() convet failed," + ex.Message); } return(tradeBook); }