Пример #1
0
        private void Send(NewOrderSingle order)
        {
            if (!_bTdConnected)
            {
                EmitError(-1, -1, "交易服务器没有连接,无法报单");
                tdlog.Error("交易服务器没有连接,无法报单");
                return;
            }

            Instrument inst        = InstrumentManager.Instruments[order.Symbol];
            string     altSymbol   = inst.GetSymbol(Name);
            string     altExchange = inst.GetSecurityExchange(Name);
            double     tickSize    = inst.TickSize;

            CThostFtdcInstrumentField _Instrument;

            if (_dictInstruments.TryGetValue(altSymbol, out _Instrument))
            {
                //从合约列表中取交易所名与tickSize,不再依赖用户手工设置的参数了
                tickSize    = _Instrument.PriceTick;
                altExchange = _Instrument.ExchangeID;
            }

            //最小变动价格修正
            double price = order.Price;

            //市价修正,如果不连接行情,此修正不执行,得策略层处理
            CThostFtdcDepthMarketDataField DepthMarket;

            //如果取出来了,并且为有效的,涨跌停价将不为0
            _dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket);

            //市价单模拟
            if (OrdType.Market == order.OrdType)
            {
                //按买卖调整价格
                if (order.Side == Side.Buy)
                {
                    price = DepthMarket.LastPrice + LastPricePlusNTicks * tickSize;
                }
                else
                {
                    price = DepthMarket.LastPrice - LastPricePlusNTicks * tickSize;
                }
            }

            //没有设置就直接用
            if (tickSize > 0)
            {
                decimal remainder = ((decimal)price % (decimal)tickSize);
                if (remainder != 0)
                {
                    if (order.Side == Side.Buy)
                    {
                        price = Math.Ceiling(price / tickSize) * tickSize;
                    }
                    else
                    {
                        price = Math.Floor(price / tickSize) * tickSize;
                    }
                }
                else
                {
                    //正好能整除,不操作
                }
            }

            if (0 == DepthMarket.UpperLimitPrice &&
                0 == DepthMarket.LowerLimitPrice)
            {
                //涨跌停无效
            }
            else
            {
                //防止价格超过涨跌停
                if (price >= DepthMarket.UpperLimitPrice)
                {
                    price = DepthMarket.UpperLimitPrice;
                }
                else if (price <= DepthMarket.LowerLimitPrice)
                {
                    price = DepthMarket.LowerLimitPrice;
                }
            }

            int YdPosition    = 0;
            int TodayPosition = 0;

            string szCombOffsetFlag;

            if (order.Side == Side.Buy)
            {
                //买,先看有没有空单,有就平空单,没有空单,直接买开多单
                _dbInMemInvestorPosition.GetPositions(altSymbol,
                                                      TThostFtdcPosiDirectionType.Short, HedgeFlagType, out YdPosition, out TodayPosition);//TThostFtdcHedgeFlagType.Speculation
            }
            else//是否要区分Side.Sell与Side.SellShort呢?
            {
                //卖,先看有没有多单,有就平多单,没有多单,直接买开空单
                _dbInMemInvestorPosition.GetPositions(altSymbol,
                                                      TThostFtdcPosiDirectionType.Long, HedgeFlagType, out YdPosition, out TodayPosition);
            }

            List <SOrderSplitItem> OrderSplitList = new List <SOrderSplitItem>();
            SOrderSplitItem        orderSplitItem;

            //根据 梦翔 与 马不停蹄 的提示,新加在Text域中指定开平标志的功能
            int nOpenCloseFlag = 0;

            if (order.Text.StartsWith(OpenPrefix))
            {
                nOpenCloseFlag = 1;
            }
            else if (order.Text.StartsWith(ClosePrefix))
            {
                nOpenCloseFlag = -1;
            }
            else if (order.Text.StartsWith(CloseTodayPrefix))
            {
                nOpenCloseFlag = -2;
            }
            else if (order.Text.StartsWith(CloseYesterdayPrefix))
            {
                nOpenCloseFlag = -3;
            }

            int leave = (int)order.OrderQty;

            //是否上海?上海先平今,然后平昨,最后开仓
            //使用do主要是想利用break功能
            //平仓部分
            do
            {
                //指定开仓,直接跳过
                if (nOpenCloseFlag > 0)
                {
                    break;
                }

                //表示指定平今与平昨
                if (nOpenCloseFlag < -1)
                {
                    if (-2 == nOpenCloseFlag)
                    {
                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseToday, (byte)TThostFtdcOffsetFlagType.CloseToday };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);
                    }
                    else
                    {
                        //肯定是-3了
                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseYesterday, (byte)TThostFtdcOffsetFlagType.CloseYesterday };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);
                    }

                    orderSplitItem.qty = leave;
                    orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                    OrderSplitList.Add(orderSplitItem);

                    leave = 0;

                    break;
                }

                if (SupportCloseToday.Contains(altExchange))
                {
                    //先看平今
                    if (leave > 0 && TodayPosition > 0)
                    {
                        int min = Math.Min(TodayPosition, leave);
                        leave -= min;

                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseToday, (byte)TThostFtdcOffsetFlagType.CloseToday };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                        orderSplitItem.qty = min;
                        orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                        OrderSplitList.Add(orderSplitItem);
                    }
                    if (leave > 0 && YdPosition > 0)
                    {
                        int min = Math.Min(YdPosition, leave);
                        leave -= min;

                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseYesterday, (byte)TThostFtdcOffsetFlagType.CloseYesterday };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                        orderSplitItem.qty = min;
                        orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                        OrderSplitList.Add(orderSplitItem);
                    }
                }
                else
                {
                    //平仓
                    int position = TodayPosition + YdPosition;
                    if (leave > 0 && position > 0)
                    {
                        int min = Math.Min(position, leave);
                        leave -= min;

                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.Close, (byte)TThostFtdcOffsetFlagType.Close };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                        orderSplitItem.qty = min;
                        orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                        OrderSplitList.Add(orderSplitItem);
                    }
                }
            } while (false);

            do
            {
                //指定平仓,直接跳过
                if (nOpenCloseFlag < 0)
                {
                    break;
                }

                if (leave > 0)
                {
                    byte[] bytes = { (byte)TThostFtdcOffsetFlagType.Open, (byte)TThostFtdcOffsetFlagType.Open };
                    szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                    orderSplitItem.qty = leave;
                    orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                    OrderSplitList.Add(orderSplitItem);

                    leave = 0;
                }
            } while (false);

            if (leave > 0)
            {
                tdlog.Info("CTP:还剩余{0}手,你应当是强制指定平仓了,但持仓数小于要平手数", leave);
            }

            //将第二腿也设置成一样,这样在使用组合时这地方不用再调整
            byte[] bytes2          = { (byte)HedgeFlagType, (byte)HedgeFlagType };
            string szCombHedgeFlag = System.Text.Encoding.Default.GetString(bytes2, 0, bytes2.Length);

            bool bSupportMarketOrder = SupportMarketOrder.Contains(altExchange);

            tdlog.Info("Side:{0},Price:{1},LastPrice:{2},Qty:{3},Text:{4},YdPosition:{5},TodayPosition:{6}",
                       order.Side, order.Price, DepthMarket.LastPrice, order.OrderQty, order.Text, YdPosition, TodayPosition);

            TThostFtdcDirectionType           Direction           = order.Side == Side.Buy ? TThostFtdcDirectionType.Buy : TThostFtdcDirectionType.Sell;
            TThostFtdcOrderPriceTypeType      OrderPriceType      = TThostFtdcOrderPriceTypeType.LimitPrice;
            TThostFtdcTimeConditionType       TimeCondition       = TThostFtdcTimeConditionType.GFD;
            TThostFtdcContingentConditionType ContingentCondition = TThostFtdcContingentConditionType.Immediately;
            TThostFtdcVolumeConditionType     VolumeCondition     = TThostFtdcVolumeConditionType.AV;

            switch (order.TimeInForce)
            {
            case TimeInForce.IOC:
                TimeCondition   = TThostFtdcTimeConditionType.IOC;
                VolumeCondition = TThostFtdcVolumeConditionType.AV;
                break;

            case TimeInForce.FOK:
                TimeCondition   = TThostFtdcTimeConditionType.IOC;
                VolumeCondition = TThostFtdcVolumeConditionType.CV;
                break;

            default:
                break;
            }

            foreach (SOrderSplitItem it in OrderSplitList)
            {
                int nRet = 0;

                switch (order.OrdType)
                {
                case OrdType.Limit:
                    break;

                case OrdType.Market:
                    if (SwitchMakertOrderToLimitOrder || !bSupportMarketOrder)
                    {
                    }
                    else
                    {
                        price          = 0;
                        OrderPriceType = TThostFtdcOrderPriceTypeType.AnyPrice;
                        //TimeCondition = TThostFtdcTimeConditionType.IOC;
                    }
                    break;

                default:
                    tdlog.Warn("没有实现{0}", order.OrdType);
                    return;
                }

                nRet = TraderApi.TD_SendOrder(m_pTdApi,
                                              altSymbol,
                                              Direction,
                                              it.szCombOffsetFlag,
                                              szCombHedgeFlag,
                                              it.qty,
                                              price,
                                              OrderPriceType,
                                              TimeCondition,
                                              ContingentCondition,
                                              order.StopPx,
                                              VolumeCondition);

                if (nRet > 0)
                {
                    _OrderRef2Order.Add(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), order as SingleOrder);
                }
            }
        }
Пример #2
0
        private void Send(NewOrderSingle order)
        {
            if (!_bTdConnected)
            {
                EmitError(-1, -1, "交易服务器没有连接,无法报单");
                return;
            }

            Instrument inst        = InstrumentManager.Instruments[order.Symbol];
            string     altSymbol   = inst.GetSymbol(this.Name);
            string     altExchange = inst.GetSecurityExchange(this.Name);

            double price;
            CThostFtdcDepthMarketDataField DepthMarket;

            if (_dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket))
            {
                //没有设置就直接用
                if (inst.TickSize > 0)
                {
                    //将价格调整为最小价格的整数倍,此处是否有问题?到底应当是向上调还是向下调呢?此处先这样
                    double num = 0;
                    if (order.Side == Side.Buy)
                    {
                        num = Math.Round(order.Price / inst.TickSize, 0, MidpointRounding.AwayFromZero);
                    }
                    else
                    {
                        num = Math.Round(order.Price / inst.TickSize, 0, MidpointRounding.AwayFromZero);
                    }

                    price = inst.TickSize * num;
                    string PF = string.Format("{{0:{0}}}", inst.PriceDisplay);
                    price = Convert.ToDouble(string.Format(PF, price));
                }
                else
                {
                    price = order.Price;
                }


                //市价修正
                if (price >= DepthMarket.UpperLimitPrice)
                {
                    price = DepthMarket.UpperLimitPrice;
                }
                else if (price <= DepthMarket.LowerLimitPrice)
                {
                    price = DepthMarket.LowerLimitPrice;
                }

                int YdPosition    = 0;
                int TodayPosition = 0;

                string szCombOffsetFlag;
                if (order.Side == Side.Buy)
                {
                    //买,先看有没有空单,有就平空单,没有空单,直接买开多单
                    _dbInMemInvestorPosition.GetPositions(altSymbol,
                                                          TThostFtdcPosiDirectionType.Short, TThostFtdcHedgeFlagType.Speculation, out YdPosition, out TodayPosition);
                }
                else//是否要区分Side.Sell与Side.SellShort呢?
                {
                    //卖,先看有没有多单,有就平多单,没有多单,直接买开空单
                    _dbInMemInvestorPosition.GetPositions(altSymbol,
                                                          TThostFtdcPosiDirectionType.Long, TThostFtdcHedgeFlagType.Speculation, out YdPosition, out TodayPosition);
                }

                List <SOrderSplitItem> OrderSplitList = new List <SOrderSplitItem>();
                SOrderSplitItem        orderSplitItem;

                //根据 梦翔 与 马不停蹄 的提示,新加在Text域中指定开平标志的功能
                int nOpenCloseFlag = 0;
                if (order.Text.StartsWith(OpenPrefix))
                {
                    nOpenCloseFlag = 1;
                }
                else if (order.Text.StartsWith(ClosePrefix))
                {
                    nOpenCloseFlag = -1;
                }

                int leave = (int)order.OrderQty;

                //是否上海?上海先平今,然后平昨,最后开仓
                //使用do主要是想利用break功能
                //平仓部分
                do
                {
                    //指定开仓,直接跳过
                    if (1 == nOpenCloseFlag)
                    {
                        break;
                    }

                    if (SupportCloseToday.Contains(altExchange))
                    {
                        //先看平今
                        if (leave > 0 && TodayPosition > 0)
                        {
                            int min = Math.Min(TodayPosition, leave);
                            leave -= min;

                            byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseToday, (byte)TThostFtdcOffsetFlagType.CloseToday };
                            szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                            orderSplitItem.qty = min;
                            orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                            OrderSplitList.Add(orderSplitItem);
                        }
                        if (leave > 0 && YdPosition > 0)
                        {
                            int min = Math.Min(YdPosition, leave);
                            leave -= min;

                            byte[] bytes = { (byte)TThostFtdcOffsetFlagType.CloseYesterday, (byte)TThostFtdcOffsetFlagType.CloseYesterday };
                            szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                            orderSplitItem.qty = min;
                            orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                            OrderSplitList.Add(orderSplitItem);
                        }
                    }
                    else
                    {
                        //平仓
                        int position = TodayPosition + YdPosition;
                        if (leave > 0 && position > 0)
                        {
                            int min = Math.Min(position, leave);
                            leave -= min;

                            byte[] bytes = { (byte)TThostFtdcOffsetFlagType.Close, (byte)TThostFtdcOffsetFlagType.Close };
                            szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                            orderSplitItem.qty = min;
                            orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                            OrderSplitList.Add(orderSplitItem);
                        }
                    }
                } while (false);

                do
                {
                    //指定平仓,直接跳过
                    if (-1 == nOpenCloseFlag)
                    {
                        break;
                    }

                    if (leave > 0)
                    {
                        leave = 0;

                        byte[] bytes = { (byte)TThostFtdcOffsetFlagType.Open, (byte)TThostFtdcOffsetFlagType.Open };
                        szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);

                        orderSplitItem.qty = leave;
                        orderSplitItem.szCombOffsetFlag = szCombOffsetFlag;
                        OrderSplitList.Add(orderSplitItem);
                    }
                } while (false);

                if (leave > 0)
                {
                    string strErr = string.Format("CTP:还剩余{0}手,你应当是强制指定平仓了,但持仓数小于要平手数", leave);
                    Console.WriteLine(strErr);
                    EmitError(-1, -1, strErr);
                }

                //目前默认只支持投机,并且将第二腿也设置成投机,这样在使用组合时这地方不用再调整
                //byte[] bytes = { (byte)TThostFtdcHedgeFlagType.Speculation, (byte)TThostFtdcHedgeFlagType.Speculation };
                //string szCombHedgeFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length);
                string szCombHedgeFlag = "11";//这样好直接啊!两个投机

                foreach (SOrderSplitItem it in OrderSplitList)
                {
                    int nRet = 0;

                    switch (order.OrdType)
                    {
                    case OrdType.Limit:
                        nRet = TraderApi.TD_SendOrder(m_pTdApi,
                                                      altSymbol,
                                                      order.Side == Side.Buy ? TThostFtdcDirectionType.Buy : TThostFtdcDirectionType.Sell,
                                                      it.szCombOffsetFlag,
                                                      szCombHedgeFlag,
                                                      it.qty,
                                                      price,
                                                      TThostFtdcOrderPriceTypeType.LimitPrice,
                                                      TThostFtdcTimeConditionType.GFD,
                                                      TThostFtdcContingentConditionType.Immediately,
                                                      order.StopPx);
                        break;

                    case OrdType.Market:
                        nRet = TraderApi.TD_SendOrder(m_pTdApi,
                                                      altSymbol,
                                                      order.Side == Side.Buy ? TThostFtdcDirectionType.Buy : TThostFtdcDirectionType.Sell,
                                                      it.szCombOffsetFlag,
                                                      szCombHedgeFlag,
                                                      it.qty,
                                                      order.Side == Side.Buy ? DepthMarket.UpperLimitPrice : DepthMarket.LowerLimitPrice,
                                                      TThostFtdcOrderPriceTypeType.LimitPrice,
                                                      TThostFtdcTimeConditionType.GFD,
                                                      TThostFtdcContingentConditionType.Immediately,
                                                      order.StopPx);
                        break;

                    default:
                        EmitError(-1, -1, string.Format("没有实现{0}", order.OrdType));
                        break;
                    }

                    if (nRet > 0)
                    {
                        _OrderRef2Order.Add(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), order as SingleOrder);
                    }
                }
            }
        }