private void CTPOnRspQryInstrument(ref CThostFtdcInstrumentField pInstrument, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { var field = new InstrumentField { //ExchangeID = pInstrument.ExchangeID, InstrumentID = pInstrument.InstrumentID, PriceTick = pInstrument.PriceTick, ProductClass = pInstrument.ProductClass == TThostFtdcProductClassType.THOST_FTDC_PC_Futures ? ProductClassType.Futures : pInstrument.ProductClass == TThostFtdcProductClassType.THOST_FTDC_PC_Options ? ProductClassType.Options : pInstrument.ProductClass == TThostFtdcProductClassType.THOST_FTDC_PC_Combination ? ProductClassType.Combination : pInstrument.ProductClass == TThostFtdcProductClassType.THOST_FTDC_PC_SpotOption ? ProductClassType.SpotOption : ProductClassType.Futures, ProductID = pInstrument.ProductID, VolumeMultiple = pInstrument.VolumeMultiple, MaxOrderVolume = pInstrument.MaxLimitOrderVolume, }; Exchange exc; if (Enum.TryParse(pInstrument.ExchangeID, out exc)) { field.ExchangeID = exc; } DicInstrumentField.TryAdd(pInstrument.InstrumentID, field); if (bIsLast) { //查询流控 _tIsLogin = new Thread(qryPosiAccount); _tIsLogin.Start(); //Thread.Sleep(1100); //_t.ReqQryTradingAccount(_broker, _investor); } }
public int ReqOrderInsert(string pInstrument, DirectionType pDirection, OffsetType pOffset, double pPrice, int pVolume, OrderType pType = OrderType.Limit, int pCustom = 0, HedgeType pHedge = HedgeType.Speculation) { InstrumentField dif; ExchangeStatusType es; //小节收盘:等待重新开盘 if (DicInstrumentField.TryGetValue(pInstrument, out dif)) { if (_initFlow) { pPrice += _floConfig.FirstAddTicks * (pDirection == DirectionType.Buy ? 1 : -1) * dif.PriceTick; } //限定在涨跌板范围内 MarketData f; if (_q == null) { ShowInfo("行情接口异常"); return(-1); } if (!_q.DicTick.TryGetValue(pInstrument, out f)) { _q.ReqSubscribeMarketData(pInstrument); Thread.Sleep(200); } if (_q.DicTick.TryGetValue(pInstrument, out f)) { ShowInfo($"合约{pInstrument}无行情"); } else { pPrice = Math.Max(f.LowerLimitPrice, Math.Min(f.UpperLimitPrice, pPrice)); } //下单前修正价格为最小变动的倍数 pPrice = (int)(pPrice / dif.PriceTick) * dif.PriceTick; if (DicExcStatus.TryGetValue(dif.ProductID, out es) || DicExcStatus.TryGetValue(dif.InstrumentID, out es) || DicExcStatus.TryGetValue(dif.ExchangeID.ToString(), out es)) { if (es == ExchangeStatusType.NoTrading) //小节收盘中:待处理 { ShowInfo($"小节收盘,待重新开盘后再发委托:{pInstrument},{pDirection},{ pOffset},{ pPrice},{ pVolume},{pCustom}"); _listWaitTrading.Add(new object[] { pInstrument, pDirection, pOffset, pPrice, pVolume, pType, pCustom, pHedge }); return(0); } } } return(base.ReqOrderInsert(pInstrument, pDirection, pOffset, pPrice, pVolume, pCustom, pType, pHedge)); }
private void TradeExt_OnRtnCancel(object sender, OrderArgs e) { if (!e.Value.IsLocal) { return; } if (_q == null) { ShowInfo("请先赋值行情接口"); return; } MarketData tick; if (!_q.DicTick.TryGetValue(e.Value.InstrumentID, out tick)) { return; } var id = e.Value.Custom + 1; var times = e.Value.Custom % 100; if (times >= _floConfig.FollowTimes) //达到最大追单次数 { var price = e.Value.Direction == DirectionType.Buy ? tick.UpperLimitPrice : tick.LowerLimitPrice; ShowInfo($"[{e.Value.Custom}]达到最大追单次数({_floConfig.FollowTimes},板价追单[custom:{id}][{e.Value.InstrumentID},{e.Value.Direction},{ e.Value.Offset},{ e.Value.Direction},{price},{ e.Value.VolumeLeft}])"); ReqOrderInsert(e.Value.InstrumentID, e.Value.Direction, e.Value.Offset, price, e.Value.VolumeLeft, OrderType.Limit, id); } else { InstrumentField instField; if (!DicInstrumentField.TryGetValue(e.Value.InstrumentID, out instField)) { return; } var price = e.Value.Direction == DirectionType.Buy ? (tick.AskPrice + _floConfig.NotFirstAddticks * instField.PriceTick) : (tick.BidPrice - _floConfig.NotFirstAddticks * instField.PriceTick); ShowInfo($"[{e.Value.Custom}]第{times - 1}次追单[id:{id}][{e.Value.InstrumentID},{e.Value.Direction},{ e.Value.Offset},{ e.Value.Direction},{price},{ e.Value.VolumeLeft}]"); ReqOrderInsert(e.Value.InstrumentID, e.Value.Direction, e.Value.Offset, price, e.Value.VolumeLeft, OrderType.Limit, id); } }
private void CTPOnRspQryInvestorPosition(ref CThostFtdcInvestorPositionField pInvestorPosition, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (!string.IsNullOrEmpty(pInvestorPosition.InstrumentID)) { var f = pInvestorPosition; _listPosi.Add(f); } if (bIsLast) { foreach (var g in _listPosi.GroupBy(p => p.InstrumentID + "_" + p.PosiDirection)) { var id = g.First(); //整理持仓数据 HedgeType hedge = HedgeType.Speculation; switch (id.HedgeFlag) { case TThostFtdcHedgeFlagType.THOST_FTDC_HF_Speculation: hedge = HedgeType.Speculation; break; case TThostFtdcHedgeFlagType.THOST_FTDC_HF_Arbitrage: hedge = HedgeType.Arbitrage; break; case TThostFtdcHedgeFlagType.THOST_FTDC_HF_Hedge: hedge = HedgeType.Hedge; break; } DirectionType dire = DirectionType.Buy; if (g.First().PosiDirection == TThostFtdcPosiDirectionType.THOST_FTDC_PD_Short) { dire = DirectionType.Sell; } var key = id.InstrumentID + "_" + dire; var pf = DicPositionField.GetOrAdd(key, new PositionField { InstrumentID = id.InstrumentID, Direction = dire, Hedge = hedge, }); //if (pInvestorPosition.PositionDate == TThostFtdcPositionDateType.THOST_FTDC_PSD_Today) //{ // pf.TdPosition = pInvestorPosition.Position; // pf.TdCost = pf.TdPosition == 0 ? 0 : (pInvestorPosition.PositionCost /*pInvestorPosition.TodayPosition * pf.TdPosition*/); //} //if (pInvestorPosition.PositionDate == TThostFtdcPositionDateType.THOST_FTDC_PSD_History) //{ // pf.YdPosition = pInvestorPosition.Position; // pf.YdCost = pInvestorPosition.PreSettlementPrice * pf.YdPosition * DicInstrumentField[pf.InstrumentID].VolumeMultiple; // //pf.YdCost = pInvestorPosition.PositionCost / pInvestorPosition.YdPosition * pf.YdPosition; //} pf.Position = g.Sum(n => n.Position); // pf.TdPosition + pf.YdPosition; pf.TdPosition = g.Sum(n => n.TodayPosition); pf.YdPosition = pf.Position - pf.TdPosition; // g.Sum(n => n.YdPosition); // 交易合约可能不存在(如交易所合约的SP合约) if (DicInstrumentField.ContainsKey(pf.InstrumentID)) { pf.Price = pf.Position <= 0 ? 0 : (g.Sum(n => n.PositionCost) / DicInstrumentField[pf.InstrumentID].VolumeMultiple / pf.Position); } else { pf.Price = pf.Position <= 0 ? 0 : (g.Sum(n => n.PositionCost) / DicInstrumentField[pf.InstrumentID.Split('&')[1]].VolumeMultiple / pf.Position); } pf.CloseProfit = g.Sum(n => n.CloseProfit); pf.PositionProfit = g.Sum(n => n.PositionProfit); pf.Commission = g.Sum(n => n.Commission); pf.Margin = g.Sum(n => n.UseMargin); } TradingAccount.CloseProfit = _listPosi.Sum(n => n.CloseProfit); TradingAccount.PositionProfit = _listPosi.Sum(n => n.PositionProfit); TradingAccount.Commission = _listPosi.Sum(n => n.Commission); TradingAccount.Fund = TradingAccount.PreBalance + TradingAccount.CloseProfit + TradingAccount.PositionProfit - TradingAccount.Commission; TradingAccount.FrozenCash = _listPosi.Sum(n => n.FrozenCash); //由查帐户资金函数处理,原因:保证金有单边收的情况无法用持仓统计 //TradingAccount.CurrMargin = _listPosi.Sum(n => n.UseMargin); //TradingAccount.Available = TradingAccount.Fund - TradingAccount.CurrMargin - TradingAccount.FrozenCash; //TradingAccount.Risk = TradingAccount.CurrMargin / TradingAccount.Fund; _listPosi.Clear();//清除,以便得到结果是重新添加 } }