/// <summary> /// 检查平仓 /// </summary> /// <param name="data">最新持仓数据</param> /// <param name="ceil">止盈位</param> /// <param name="floor">止损位</param> public static void checkClose(List <InvestorPosition> data, double ceil, double floor) { //取小数部分,止盈为正,止损位负 int dataSize = data.Count; Dictionary <String, String> codes = new Dictionary <string, string>(); //循环遍历数据 for (int i = 0; i < dataSize; i++) { InvestorPosition investorPosition = data[i]; String key = investorPosition.m_code + investorPosition.m_posiDirection; //判断该持仓是新增的还是减少的 lock (m_investorPositions) { if (m_investorPositions.ContainsKey(key)) { if (m_investorPositions[key].m_position != investorPosition.m_position) { codes[investorPosition.m_code] = ""; } } else { codes[investorPosition.m_code] = ""; } //更新内存 m_investorPositions[key] = investorPosition; } //获取行情数据 SecurityLatestData latestData = null; lock (m_latestDatas) { if (m_latestDatas.ContainsKey(investorPosition.m_code)) { latestData = m_latestDatas[investorPosition.m_code]; } } //openPrice字段是0 if (latestData != null && investorPosition.m_position > 0) { double openPrice = investorPosition.m_openCost / investorPosition.m_position; //获取当前价格与开仓价的差额 if (openPrice != 0) { //获取代码 String code = investorPosition.m_code; //获取方向 String direction = investorPosition.m_posiDirection; //处理买开仓 if (investorPosition.m_posiDirection == "买") { //获取盈亏比例 double ratio = latestData.m_close / openPrice; String strClose = String.Format("现价/开仓价:{0},止盈位:{1},止损位:{2}", ratio, ceil, floor); //判断止盈 if (ratio >= ceil) //如果是止盈,右边应该1.03 { askOrBidClose(investorPosition, code, direction, latestData.m_close, openPrice, 1); } //判断止损 else if (ratio <= floor) //如果是止损,右边应该是0.99 { askOrBidClose(investorPosition, code, direction, latestData.m_close, openPrice, 2); } } //处理卖开仓 else if (investorPosition.m_posiDirection == "卖") { //获取当前价格与开仓价的差额,但是方向相反 double ratio = latestData.m_close / openPrice; double subCeil = ceil - 1; //也就是0.03 double subFloor = 1 - floor; //也就是0.01 String strClose = String.Format("现价/开仓价:{0},止盈位:{1},止损位:{2}", ratio, 1 - subCeil, 1 + subFloor); //判断止盈 if (ratio <= 1 - subCeil) //如果止盈是0.03,右边应该是0.97 { askOrBidClose(investorPosition, code, direction, latestData.m_close, openPrice, 1); } //判断止损 else if (ratio >= 1 + subFloor) //如果止损是0.01,右边应该是1.01 { askOrBidClose(investorPosition, code, direction, latestData.m_close, openPrice, 2); } } } } } }
/// <summary> /// 平仓 /// </summary> /// <param name="investorPosition">持仓</param> /// <param name="code">代码</param> /// <param name="direction">方向</param> /// <param name="close">最新价</param> /// <param name="openPrice">开仓价</param> /// <param name="state">state=0为手动平仓,其余为自动</param> public static void askOrBidClose(InvestorPosition investorPosition, String code, String direction, double close, double openPrice, int state) { //如果持仓为0,则不检查 if (investorPosition.m_position == 0) { return; } //获取对应的行情数据 SecurityLatestData latestData = null; lock (m_latestDatas) { if (m_latestDatas.ContainsKey(code)) { latestData = m_latestDatas[code]; } } if (latestData != null) { //获取的码表 Security security = null; lock (m_securities) { if (m_securities.ContainsKey(investorPosition.m_code)) { security = m_securities[investorPosition.m_code]; } } if (security != null) { bool canTrade = true; //检查冷却时间,一次平仓10秒后才能再次平仓 if (state != 0) { lock (m_cd2) { if (m_cd2.ContainsKey(investorPosition.m_code)) { if (m_cd2[investorPosition.m_code] > 0) { canTrade = false; } } } } //获取昨仓 int ydPosition = investorPosition.m_ydPosition; //获取今仓 int todayPosition = investorPosition.m_position - ydPosition; if (canTrade) { bool isSh = security.m_exchangeID == "SHFE"; //买开仓情况下 if (direction == "买") { //上期所处理方法 if (isSh) { //平昨 if (ydPosition > 0) { CTPDLL.askClose(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, ydPosition, '3', ""); } //平今 if (todayPosition > 0) { CTPDLL.askCloseToday(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, todayPosition, '3', ""); } } //其他交易所处理方法 else { CTPDLL.askClose(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, investorPosition.m_position, '3', ""); } //打印日志 if (state == 1) { FCStrEx.writeLog(String.Format("自动止盈,开仓价{0},当前价{1},买平仓,代码{2},价格{3},数量{4}\r\n", openPrice, close, investorPosition.m_code, latestData.m_bidPrice1, investorPosition.m_position)); } else if (state == 2) { FCStrEx.writeLog(String.Format("自动止损,开仓价{0},当前价{1},买平仓,代码{2},价格{3},数量{4}\r\n", openPrice, close, investorPosition.m_code, latestData.m_bidPrice1, investorPosition.m_position)); } //开仓冷却时间+10 lock (m_cd1) { if (m_cd1.ContainsKey(investorPosition.m_code)) { m_cd1[investorPosition.m_code] += 10; } else { m_cd1[investorPosition.m_code] = 10; } } //平仓冷却时间重置 lock (m_cd2) { m_cd2[investorPosition.m_code] = 10; } } //卖开仓情况下 else if (direction == "卖") { //上期所处理方法 if (isSh) { //平昨 if (ydPosition > 0) { CTPDLL.bidClose(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, ydPosition, '3', ""); } //平今 if (todayPosition > 0) { CTPDLL.bidCloseToday(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, todayPosition, '3', ""); } } //其他交易所处理方法 else { CTPDLL.bidClose(m_ctpID, CTPDLL.generateReqID(m_ctpID), investorPosition.m_code, security.m_exchangeID, 0, investorPosition.m_position, '3', ""); } //打印日志 if (state == 1) { FCStrEx.writeLog(String.Format("自动止盈,开仓价{0},当前价{1},卖平仓,代码{2},价格{3},数量{4}\r\n", openPrice, close, investorPosition.m_code, latestData.m_bidPrice1, investorPosition.m_position)); } else if (state == 2) { FCStrEx.writeLog(String.Format("自动止损,开仓价{0},当前价{1},卖平仓,代码{2},价格{3},数量{4}\r\n", openPrice, close, investorPosition.m_code, latestData.m_bidPrice1, investorPosition.m_position)); } //开仓冷却时间+10 lock (m_cd1) { if (m_cd1.ContainsKey(investorPosition.m_code)) { m_cd1[investorPosition.m_code] += 10; } else { m_cd1[investorPosition.m_code] = 10; } } //平仓冷却时间重置 lock (m_cd2) { m_cd2[investorPosition.m_code] = 10; } } } } } }
public override void OnRspQryInvestorPosition(ThostFtdcInvestorPositionField pInvestorPosition, ThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (pRspInfo != null && pRspInfo.ErrorID != 0) { LogCenter.Error("请求查询投资者持仓错误:" + pRspInfo.ErrorMsg); return; } if (pInvestorPosition == null) { return; } var position = new InvestorPosition { InstrumentID = pInvestorPosition.InstrumentID, BrokerID = pInvestorPosition.BrokerID, InvestorID = pInvestorPosition.InvestorID, PosiDirection = (PosiDirection)pInvestorPosition.PosiDirection, HedgeFlag = (HedgeFlag)pInvestorPosition.HedgeFlag, PositionDate = (PositionDateType)pInvestorPosition.PositionDate, YdPosition = pInvestorPosition.YdPosition, Position = pInvestorPosition.Position, LongFrozen = pInvestorPosition.LongFrozen, ShortFrozen = pInvestorPosition.ShortFrozen, LongFrozenAmount = pInvestorPosition.LongFrozenAmount, ShortFrozenAmount = pInvestorPosition.ShortFrozenAmount, OpenVolume = pInvestorPosition.OpenVolume, CloseVolume = pInvestorPosition.CloseVolume, OpenAmount = pInvestorPosition.OpenAmount, CloseAmount = pInvestorPosition.CloseAmount, PositionCost = pInvestorPosition.PositionCost, PreMargin = pInvestorPosition.PreMargin, UseMargin = pInvestorPosition.UseMargin, FrozenMargin = pInvestorPosition.FrozenMargin, FrozenCash = pInvestorPosition.FrozenCash, FrozenCommission = pInvestorPosition.FrozenCommission, CashIn = pInvestorPosition.CashIn, Commission = pInvestorPosition.Commission, CloseProfit = pInvestorPosition.CloseProfit, PositionProfit = pInvestorPosition.PositionProfit, PreSettlementPrice = pInvestorPosition.PreSettlementPrice, SettlementPrice = pInvestorPosition.SettlementPrice, TradingDay = pInvestorPosition.TradingDay, SettlementID = pInvestorPosition.SettlementID, OpenCost = pInvestorPosition.OpenCost, ExchangeMargin = pInvestorPosition.ExchangeMargin, CombPosition = pInvestorPosition.CombPosition, CombLongFrozen = pInvestorPosition.CombLongFrozen, CombShortFrozen = pInvestorPosition.CombShortFrozen, CloseProfitByDate = pInvestorPosition.CloseProfitByDate, CloseProfitByTrade = pInvestorPosition.CloseProfitByTrade, TodayPosition = pInvestorPosition.TodayPosition, MarginRateByMoney = pInvestorPosition.MarginRateByMoney, MarginRateByVolume = pInvestorPosition.MarginRateByVolume, StrikeFrozen = pInvestorPosition.StrikeFrozen, StrikeFrozenAmount = pInvestorPosition.StrikeFrozenAmount, AbandonFrozen = pInvestorPosition.AbandonFrozen, }; this.positions.Add(position); if (bIsLast) { PositionViewModel.Instance.Update(this.positions); } }