public void Connect()
 {
     if (!this.isConnected)
     {
         ReportArgs rargs = this.trader.Logon(this.ip, this.port, this.version, this.departmentID, this.accountID, this.fundID, this.password);
         if (rargs.Succeeded)
         {
             this.isConnected = true;
             if (this.timer == null)
             {
                 this.timer          = new System.Timers.Timer();
                 this.timer.Interval = this.refreshTime * 1000;
                 this.timer.Elapsed += new ElapsedEventHandler(tickTimer_Elapsed);
                 this.timer.Start();
             }
             Console.WriteLine("已登录.");
             if (Connected != null)
             {
                 Connected(this, new EventArgs());
             }
             if (StatusChanged != null)
             {
                 StatusChanged(this, new EventArgs());
             }
         }
         else
         {
             this.EmitError(this.Id, -1, rargs.ErrorInfo);
         }
     }
 }
        public ReportArgs Logon(string ip, short port, string version, short departmentID, string accountID, string fundID, string password)
        {
            this.ip           = ip;
            this.port         = port;
            this.version      = version;
            this.departmentID = departmentID;
            this.accountID    = accountID;
            this.fundID       = fundID;
            this.password     = password;
            StringBuilder errInfo = new StringBuilder(256);

            this.clientID = TDXWrapper.Logon(this.ip, this.port, this.version, this.departmentID, this.accountID, this.fundID, this.password, string.Empty, errInfo);
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID == -1)
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = errInfo.ToString();
            }
            else
            {
                reportArgs.Succeeded = true;
            }
            return(reportArgs);
        }
        public ReportArgs SendOrder(OrderSide orderSide, OrderType orderType, string securityID, float price, long quantity)
        {
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID != -1)
            {
                //股东代码似乎可以为空
                string        shareholderCode = "";
                StringBuilder errInfo         = new StringBuilder(256);
                StringBuilder result          = new StringBuilder(1024 * 1024);
                TDXWrapper.SendOrder(this.clientID, (int)orderSide, (int)orderType, shareholderCode, securityID, price, (int)quantity, result, errInfo);

                if (errInfo.ToString() != string.Empty)//下单失败
                {
                    reportArgs.Succeeded = false;
                    reportArgs.ErrorInfo = errInfo.ToString();
                }
                else//下单成功
                {
                    List <string[]> data = this.pickUp(result);
                    reportArgs.Succeeded = true;
                    if (data.Count > 1)
                    {
                        reportArgs.Result = data[1][0];//返回订单编号
                    }
                }
            }
            else
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = "交易账号未登录.";
            }
            return(reportArgs);
        }
        public ReportArgs CancelOrder(string orderID)
        {
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID != -1)
            {
                //交易所编号,似乎可以为空
                string        exchangeID = "";
                StringBuilder errInfo    = new StringBuilder(256);
                StringBuilder result     = new StringBuilder(1024 * 1024);
                TDXWrapper.CancelOrder(this.clientID, exchangeID, orderID, result, errInfo);
                if (errInfo.ToString() != string.Empty)//撤单失败
                {
                    reportArgs.Succeeded = false;
                    reportArgs.ErrorInfo = errInfo.ToString();
                }
                else//下单成功
                {
                    List <string[]> data = this.pickUp(result);
                    reportArgs.Succeeded = true;
                    if (data.Count > 1)
                    {
                        reportArgs.Result = data[1][0];
                    }
                }
            }
            else
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = "交易账号未登录.";
            }
            return(reportArgs);
        }
        public void SendOrderCancelRequest(FIXOrderCancelRequest request)
        {
            if (!this.isConnected)
            {
                this.EmitError(this.Id, -1, "The TDXTradeProvider is not connected.");
            }
            string      origOuterOrderID = request.OrigClOrdID;
            OrderRecord orderRecord      = this.orders.GetRecord(origOuterOrderID, 1);

            if (orderRecord == null)
            {
                string errorInfo = "要取消的订单没有记录。";
                this.EmitError(this.Id, -1, errorInfo);
                OrderCancelReject report = new OrderCancelReject();
                report.TransactTime     = DateTime.Now;
                report.OrigClOrdID      = request.OrigClOrdID;
                report.ClOrdID          = request.ClOrdID;
                report.CxlRejReason     = CxlRejReason.UnknownOrder;
                report.CxlRejResponseTo = CxlRejResponseTo.CancelRequest;
                report.Text             = errorInfo;
                report.OrdStatus        = OrdStatus.Rejected;
                if (OrderCancelReject != null)
                {
                    OrderCancelReject(this, new OrderCancelRejectEventArgs(report));
                }
                return;
            }
            string     origInnerOrderID = orderRecord.InnerOrderID;
            ReportArgs rargs            = this.trader.CancelOrder(origInnerOrderID);

            if (rargs.Succeeded)
            {
                Thread.Sleep(1000);
                this.updateOrders();
            }
            else
            {
                this.EmitError(this.Id, -1, rargs.ErrorInfo);
                OrderCancelReject report = new OrderCancelReject();
                report.TransactTime     = DateTime.Now;
                report.OrigClOrdID      = request.OrigClOrdID;
                report.ClOrdID          = request.ClOrdID;
                report.CxlRejReason     = CxlRejReason.BrokerOption;
                report.CxlRejResponseTo = CxlRejResponseTo.CancelRequest;
                report.Text             = rargs.ErrorInfo;
                report.OrdStatus        = OrdStatus.Rejected;
                if (OrderCancelReject != null)
                {
                    OrderCancelReject(this, new OrderCancelRejectEventArgs(report));
                }
            }
        }
        public BrokerInfo GetBrokerInfo()
        {
            BrokerInfo brokerInfo = new BrokerInfo();

            if (!this.isConnected)
            {
                this.EmitError(this.Id, -1, "The TDXTradeProvider is not connected.");
                return(brokerInfo);
            }
            ReportArgs rargs = this.trader.QueryFund();

            if (rargs.Succeeded && rargs.Result != null)
            {
                FundRecord    fundRecord    = (FundRecord)rargs.Result;
                BrokerAccount brokerAccount = new BrokerAccount("通达信-" + this.fundID);
                brokerAccount.AddField("Balance", fundRecord.Balance.ToString());
                brokerAccount.AddField("Available", fundRecord.Available.ToString());
                brokerAccount.AddField("TotalAssets", fundRecord.TotalAsserts.ToString());
                brokerAccount.AddField("Desirable", fundRecord.Desirable.ToString());
                brokerAccount.AddField("MarketValue", fundRecord.MarketValue.ToString());
                brokerAccount.AddField("Frozen", fundRecord.Frozen.ToString());
                brokerAccount.BuyingPower = fundRecord.Available;
                brokerInfo.Accounts.Add(brokerAccount);
                rargs = this.trader.QueryPositions();
                if (rargs.Succeeded && rargs.Result != null)
                {
                    List <PositionRecord> positions = (List <PositionRecord>)rargs.Result;
                    foreach (PositionRecord position in positions)
                    {
                        BrokerPosition brokerPosition = new BrokerPosition();
                        brokerPosition.SecurityExchange = position.SecurityExchange;
                        brokerPosition.Symbol           = position.SecurityExchange + "." + position.SecurityID;
                        brokerPosition.AddCustomField("Available", position.Available.ToString());
                        brokerPosition.Qty = position.Quantity;
                        brokerPosition.AddCustomField("CostPrice", position.CostPrice.ToString());
                        brokerPosition.LongQty = position.Quantity;
                        brokerAccount.AddPosition(brokerPosition);
                    }
                }
                else
                {
                    this.EmitError(this.Id, -1, rargs.ErrorInfo);
                }
            }
            else
            {
                this.EmitError(this.Id, -1, rargs.ErrorInfo);
            }


            return(brokerInfo);
        }
        public ReportArgs QueryPositions()
        {
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID != -1)
            {
                StringBuilder errInfo = new StringBuilder(256);
                StringBuilder result  = new StringBuilder(1024 * 1024);
                TDXWrapper.QueryData(this.clientID, 1, result, errInfo);
                if (errInfo.ToString() != string.Empty)//查询失败
                {
                    reportArgs.Succeeded = false;
                    reportArgs.ErrorInfo = errInfo.ToString();
                }
                else//查询成功
                {
                    List <string[]> data = this.pickUp(result);
                    reportArgs.Succeeded = true;
                    List <PositionRecord> positions = new List <PositionRecord>();
                    for (int i = 1; i < data.Count; i++)
                    {
                        PositionRecord positionRecord = new PositionRecord();
                        positionRecord.SecurityID = data[i][0];
                        positionRecord.Quantity   = double.Parse(data[i][2]);
                        positionRecord.Available  = double.Parse(data[i][3]);
                        positionRecord.CostPrice  = double.Parse(data[i][4]);
                        switch (int.Parse(data[i][11]))
                        {
                        case 1:
                            positionRecord.SecurityExchange = "SHSE";
                            break;

                        case 0:
                            positionRecord.SecurityExchange = "SZSE";
                            break;
                        }
                        positions.Add(positionRecord);
                    }
                    reportArgs.Result = positions;
                }
            }
            else
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = "交易账号未登录.";
            }
            return(reportArgs);
        }
        public ReportArgs ReLogon()
        {
            StringBuilder errInfo = new StringBuilder(256);

            this.clientID = TDXWrapper.Logon(this.ip, this.port, this.version, this.departmentID, this.accountID, this.fundID, this.password, string.Empty, errInfo);
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID == -1)
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = errInfo.ToString();
            }
            else
            {
                reportArgs.Succeeded = true;
            }
            return(reportArgs);
        }
        public ReportArgs QueryFund()
        {
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID != -1)
            {
                StringBuilder errInfo = new StringBuilder(256);
                StringBuilder result  = new StringBuilder(1024 * 1024);
                TDXWrapper.QueryData(this.clientID, 0, result, errInfo);
                if (errInfo.ToString() != string.Empty)//查询失败
                {
                    reportArgs.Succeeded = false;
                    reportArgs.ErrorInfo = errInfo.ToString();
                }
                else//查询成功
                {
                    List <string[]> data = this.pickUp(result);
                    reportArgs.Succeeded = true;
                    if (data.Count > 1)
                    {
                        FundRecord fundRecord = new FundRecord();
                        fundRecord.Balance      = double.Parse(data[1][1]);
                        fundRecord.Available    = double.Parse(data[1][2]);
                        fundRecord.Frozen       = double.Parse(data[1][3]);
                        fundRecord.Desirable    = double.Parse(data[1][4]);
                        fundRecord.TotalAsserts = double.Parse(data[1][5]);
                        fundRecord.MarketValue  = double.Parse(data[1][6]);
                        reportArgs.Result       = fundRecord;
                    }
                }
            }
            else
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = "交易账号未登录.";
            }
            return(reportArgs);
        }
        private void updateOrders()
        {
            if (!this.isConnected)
            {
                this.EmitError(this.Id, -1, "The TDXTradeProvider is not connected.");
            }
            lock (this.updating)
            {
                ReportArgs rargs = this.trader.QueryOrders();
                if (rargs.Succeeded)
                {
                    List <OrderRecord> orderRecords = (List <OrderRecord>)rargs.Result;
                    foreach (OrderRecord orderRecord in orderRecords)
                    {
                        bool        needReport      = false;
                        OrderRecord prevOrderRecord = this.orders.GetRecord(orderRecord.InnerOrderID, 0);
                        if (prevOrderRecord == null)
                        {
                            prevOrderRecord = this.orders.SearchRecord(orderRecord);
                        }
                        if (prevOrderRecord != null)
                        {
                            if (prevOrderRecord.OrderStatus != orderRecord.OrderStatus)
                            {
                                needReport = true;
                            }
                            else if (orderRecord.OrderStatus == OrderStatus.PartiallyFilled &&
                                     prevOrderRecord.CumQty < orderRecord.CumQty)
                            {
                                needReport = true;
                            }
                        }
                        if (needReport)
                        {
                            ExecutionReport report = new ExecutionReport();
                            report.TransactTime = orderRecord.TransactTime;
                            switch (orderRecord.OrderStatus)
                            {
                            case OrderStatus.New:
                                report.ExecType  = ExecType.New;
                                report.OrdStatus = OrdStatus.New;
                                break;

                            case OrderStatus.PartiallyFilled:
                                report.ExecType  = ExecType.PartialFill;
                                report.OrdStatus = OrdStatus.PartiallyFilled;
                                break;

                            case OrderStatus.Filled:
                                report.ExecType  = ExecType.Fill;
                                report.OrdStatus = OrdStatus.Filled;
                                break;

                            case OrderStatus.PendingCancel:
                                report.ExecType  = ExecType.PendingCancel;
                                report.OrdStatus = OrdStatus.PendingCancel;
                                break;

                            case OrderStatus.Cancelled:
                                report.ExecType  = ExecType.Cancelled;
                                report.OrdStatus = OrdStatus.Cancelled;
                                break;

                            case OrderStatus.Rejected:
                                report.ExecType  = ExecType.Rejected;
                                report.OrdStatus = OrdStatus.Rejected;
                                break;

                            default:
                                report.ExecType  = ExecType.Undefined;
                                report.OrdStatus = OrdStatus.Undefined;
                                break;
                            }
                            report.ClOrdID = prevOrderRecord.OuterOrderID;
                            if (orderRecord.OrderStatus == OrderStatus.PendingCancel || orderRecord.OrderStatus == OrderStatus.Cancelled)
                            {
                                report.OrigClOrdID = prevOrderRecord.OuterOrderID;
                            }

                            report.OrderQty  = orderRecord.OrderQty;
                            report.AvgPx     = orderRecord.AvgPx;
                            report.CumQty    = orderRecord.CumQty;
                            report.LeavesQty = orderRecord.OrderQty - orderRecord.CumQty;
                            switch (orderRecord.OrderSide)
                            {
                            case (OrderSide.Buy):
                                report.Side = Side.Buy;
                                break;

                            case (OrderSide.Sell):
                                report.Side = Side.Sell;
                                break;

                            default:
                                report.Side = Side.Undefined;
                                break;
                            }
                            //计算费率
                            if (report.CumQty > 0)
                            {
                                report.Commission = this.commission * report.CumQty * report.AvgPx;
                                report.CommType   = CommType.Absolute;
                                if (report.Commission < this.minCommission)
                                {
                                    report.Commission = this.minCommission;
                                }
                                if (report.Side == Side.Sell)
                                {
                                    report.Commission += this.stampDuty * report.CumQty * report.AvgPx;
                                }
                            }
                            if (ExecutionReport != null)
                            {
                                ExecutionReport(this, new ExecutionReportEventArgs(report));
                            }
                            prevOrderRecord.OrderStatus = orderRecord.OrderStatus;
                            prevOrderRecord.AvgPx       = orderRecord.AvgPx;
                            prevOrderRecord.CumQty      = orderRecord.CumQty;
                        }
                    }
                }
                else
                {
                    this.EmitError(this.Id, -1, rargs.ErrorInfo);
                }
            }
        }
        public void SendNewOrderSingle(NewOrderSingle order)
        {
            if (!this.isConnected)
            {
                this.EmitError(this.Id, -1, "The TDXTradeProvider is not connected.");
            }
            try
            {
                Instrument curInstrument = InstrumentManager.Instruments[order.Symbol];
                string     securityID    = curInstrument.SecurityID;
                OrderSide  orderSide;
                switch (order.Side)
                {
                case Side.Buy:
                    orderSide = OrderSide.Buy;
                    break;

                case Side.Sell:
                    orderSide = OrderSide.Sell;
                    break;

                default:
                    throw new Exception("不支持的买卖指令。");
                }
                OrderType orderType;
                switch (order.OrdType)
                {
                case OrdType.Market:
                    orderType = OrderType.CancelAfterFiveQuoteTransaction;
                    break;

                case OrdType.Limit:
                    orderType = OrderType.Limit;
                    break;

                default:
                    throw new Exception("不支持的订单类型");
                }
                ReportArgs rargs = this.trader.SendOrder(orderSide, orderType, securityID, (float)order.Price, (long)order.OrderQty);
                if (rargs.Succeeded)                                //下单成功
                {
                    string      orderID     = (string)rargs.Result; //委托编号
                    OrderRecord orderRecord = new OrderRecord();
                    orderRecord.InnerOrderID = orderID;
                    orderRecord.OuterOrderID = order.ClOrdID;
                    orderRecord.SecurityID   = order.SecurityID;
                    orderRecord.OrderStatus  = OrderStatus.New;
                    orderRecord.OrderSide    = orderSide;
                    orderRecord.OrderType    = orderType;
                    orderRecord.OrderPrice   = order.Price;
                    orderRecord.OrderQty     = (long)order.OrderQty;
                    orderRecord.AvgPx        = 0.0;
                    orderRecord.CumQty       = 0;
                    orderRecord.TransactTime = Clock.Now;
                    lock (this.orders)
                    {
                        this.orders.AddRecord(orderRecord, orderID, order.ClOrdID);
                    }
                    ExecutionReport report = new ExecutionReport();
                    report.TransactTime = orderRecord.TransactTime;
                    report.ExecType     = ExecType.New;
                    report.ClOrdID      = order.ClOrdID;
                    report.OrdStatus    = OrdStatus.New;
                    report.AvgPx        = 0.0;
                    report.CumQty       = 0;
                    report.OrderQty     = order.OrderQty;
                    report.Price        = order.Price;
                    report.LeavesQty    = order.OrderQty;
                    report.Side         = order.Side;
                    if (order.OrdType == OrdType.Limit)
                    {
                        report.TimeInForce = TimeInForce.Day;//强制限价单为当日有效
                    }
                    if (ExecutionReport != null)
                    {
                        ExecutionReport(this, new ExecutionReportEventArgs(report));
                    }
                    Thread.Sleep(1000);
                    this.updateOrders();
                }
                else//下单失败
                {
                    this.EmitError(this.Id, -1, rargs.ErrorInfo);
                    ExecutionReport report = new ExecutionReport();
                    report.TransactTime = DateTime.Now;
                    report.ExecType     = ExecType.Rejected;
                    report.ClOrdID      = order.ClOrdID;
                    report.OrdStatus    = OrdStatus.Rejected;
                    report.AvgPx        = 0.0;
                    report.CumQty       = 0;
                    report.OrderQty     = order.OrderQty;
                    report.Price        = order.Price;
                    report.LeavesQty    = order.OrderQty;
                    report.Side         = order.Side;
                    report.Text         = rargs.ErrorInfo;
                    if (ExecutionReport != null)
                    {
                        ExecutionReport(this, new ExecutionReportEventArgs(report));
                    }
                }
            }catch (Exception ex)
            {
                this.EmitError(this.Id, -1, ex.Message);
            }
        }
        public ReportArgs QueryOrders()
        {
            ReportArgs reportArgs = new ReportArgs();

            if (this.clientID != -1)
            {
                StringBuilder errInfo = new StringBuilder(256);
                StringBuilder result  = new StringBuilder(1024 * 1024);
                TDXWrapper.QueryData(this.clientID, 2, result, errInfo);
                if (errInfo.ToString() != string.Empty)//查询失败
                {
                    reportArgs.Succeeded = false;
                    reportArgs.ErrorInfo = errInfo.ToString();
                }
                else//查询成功
                {
                    List <string[]> data = this.pickUp(result);
                    reportArgs.Succeeded = true;
                    List <OrderRecord> resultList = new List <OrderRecord>();
                    string             dateString = DateTime.Today.ToString("yyyy-MM-dd");
                    for (int i = 1; i < data.Count; i++)
                    {
                        OrderRecord orderRecord = new OrderRecord();
                        orderRecord.TransactTime = DateTime.Parse(dateString + " " + data[i][0]);
                        orderRecord.SecurityID   = data[i][1];
                        orderRecord.OrderSide    = (OrderSide)int.Parse(data[i][3]);
                        switch (data[i][6])
                        {
                        case "待报":
                            orderRecord.OrderStatus = OrderStatus.PendingNew;
                            break;

                        case "已报":
                            orderRecord.OrderStatus = OrderStatus.New;
                            break;

                        case "部分成交":
                            orderRecord.OrderStatus = OrderStatus.PartiallyFilled;
                            break;

                        case "已成":
                            orderRecord.OrderStatus = OrderStatus.Filled;
                            break;

                        case "已报待撤":
                            orderRecord.OrderStatus = OrderStatus.PendingCancel;
                            break;

                        case "已撤":
                            orderRecord.OrderStatus = OrderStatus.Cancelled;
                            break;

                        default:
                            orderRecord.OrderStatus = OrderStatus.Rejected;
                            break;
                        }
                        orderRecord.OrderPrice   = double.Parse(data[i][7]);
                        orderRecord.OrderQty     = double.Parse(data[i][8]);
                        orderRecord.InnerOrderID = data[i][9];
                        orderRecord.AvgPx        = double.Parse(data[i][10]);
                        orderRecord.CumQty       = double.Parse(data[i][11]);
                        orderRecord.OrderType    = (OrderType)int.Parse(data[i][12]);
                        resultList.Add(orderRecord);
                    }
                    reportArgs.Result = resultList;
                }
            }
            else
            {
                reportArgs.Succeeded = false;
                reportArgs.ErrorInfo = "交易账号未登录.";
            }
            return(reportArgs);
        }