0. 欢迎交流
CTP_API技术交流群:767101469
github: https://github.com/nicai0609/JAVA-CTPAPI
1、前言
在同花顺软件中有显示全市场的成交明细如下图所示,API中只推自己的成交回报,那全市场的哪来的呢?其实这些数据都是可以根据CTP API接口自己通过计算得到,下面就来讲讲。
首先来看下CTP的mduserapi中深度行情结构体如下所示
///深度行情
struct CThostFtdcDepthMarketDataField
{
///交易日
TThostFtdcDateType TradingDay;
///合约代码
TThostFtdcInstrumentIDType InstrumentID;
///交易所代码
TThostFtdcExchangeIDType ExchangeID;
///合约在交易所的代码
TThostFtdcExchangeInstIDType ExchangeInstID;
///最新价
TThostFtdcPriceType LastPrice;
///上次结算价
TThostFtdcPriceType PreSettlementPrice;
///昨收盘
TThostFtdcPriceType PreClosePrice;
///昨持仓量
TThostFtdcLargeVolumeType PreOpenInterest;
///今开盘
TThostFtdcPriceType OpenPrice;
///最高价
TThostFtdcPriceType HighestPrice;
///最低价
TThostFtdcPriceType LowestPrice;
///数量
TThostFtdcVolumeType Volume;
///成交金额
TThostFtdcMoneyType Turnover;
///持仓量
TThostFtdcLargeVolumeType OpenInterest;
///今收盘
TThostFtdcPriceType ClosePrice;
///本次结算价
TThostFtdcPriceType SettlementPrice;
///涨停板价
TThostFtdcPriceType UpperLimitPrice;
///跌停板价
TThostFtdcPriceType LowerLimitPrice;
///昨虚实度
TThostFtdcRatioType PreDelta;
///今虚实度
TThostFtdcRatioType CurrDelta;
///最后修改时间
TThostFtdcTimeType UpdateTime;
///最后修改毫秒
TThostFtdcMillisecType UpdateMillisec;
///申买价一
TThostFtdcPriceType BidPrice1;
///申买量一
TThostFtdcVolumeType BidVolume1;
///申卖价一
TThostFtdcPriceType AskPrice1;
///申卖量一
TThostFtdcVolumeType AskVolume1;
///申买价二
TThostFtdcPriceType BidPrice2;
///申买量二
TThostFtdcVolumeType BidVolume2;
///申卖价二
TThostFtdcPriceType AskPrice2;
///申卖量二
TThostFtdcVolumeType AskVolume2;
///申买价三
TThostFtdcPriceType BidPrice3;
///申买量三
TThostFtdcVolumeType BidVolume3;
///申卖价三
TThostFtdcPriceType AskPrice3;
///申卖量三
TThostFtdcVolumeType AskVolume3;
///申买价四
TThostFtdcPriceType BidPrice4;
///申买量四
TThostFtdcVolumeType BidVolume4;
///申卖价四
TThostFtdcPriceType AskPrice4;
///申卖量四
TThostFtdcVolumeType AskVolume4;
///申买价五
TThostFtdcPriceType BidPrice5;
///申买量五
TThostFtdcVolumeType BidVolume5;
///申卖价五
TThostFtdcPriceType AskPrice5;
///申卖量五
TThostFtdcVolumeType AskVolume5;
///当日均价
TThostFtdcPriceType AveragePrice;
///业务日期
TThostFtdcDateType ActionDay;
};
客户调用CTP的行情接口就会收到CTP发来的行情,这个是行情快照。
2、现手和增仓
根据前后两次行情就可以计算出现手,增仓,公式如下。
现手 volume_delta = 后一笔Volume - 前一笔volume (1)
增仓 open_interest_delta = 后一笔OpenInterest - 前一笔OpenInterest (2)
代码如下:
volume_delta = data['Volume'] - self.PreDepthMarketData['Volume']
open_interest_delta = int(data['OpenInterest'] - self.PreDepthMarketData['OpenInterest'])
3、开平
根据现手和增仓我们可以计算出开平(不带方向),如下逻辑(3)
增仓=0,现手=0:未知
增仓=0,现手>0:换手
增仓>0,现手=增仓:双开
增仓>0,现手<>增仓:开仓
增仓<0,现手+增仓=0:双平
增仓<0,现手+增仓<>0:平仓
函数如下:
def get_open_interest_delta_forward(open_interest_delta, volume_delta):
"""根据成交量的差和持仓量的差来获取仓位变化的方向
return: open_interest_delta_forward_enum
"""
if open_interest_delta == 0 and volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.NONE
elif open_interest_delta == 0 and volume_delta > 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.EXCHANGE
elif open_interest_delta > 0:
if open_interest_delta - volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.OPENFWDOUBLE
else:
local_open_interest_delta_forward = open_interest_delta_forward_enum.OPEN
elif open_interest_delta < 0:
if open_interest_delta + volume_delta == 0:
local_open_interest_delta_forward = open_interest_delta_forward_enum.CLOSEFWDOUBLE
else:
local_open_interest_delta_forward = open_interest_delta_forward_enum.CLOSE
return local_open_interest_delta_forward
有了逻辑(3)之后,我们还需要知道价格趋势才能计算出方向,然后才能计算出真正的开平。根据价格比较我们可以计算出当前成交时价格是向上还是向下,如下逻辑(4)
后一笔最新价LastPrice >= 前一笔卖价一AskPrice1 :向上
后一笔最新价LastPrice <= 前一笔买价一BidPrice1 :向下
后一笔最新价LastPrice >= 后一笔卖价一AskPrice1 :向上
后一笔最新价LastPrice <= 后一笔买价一BidPrice1 :向下
除上面四种外:不变
代码如下:
def get_order_forward(last_price, ask_price1, bid_price1, pre_last_price, pre_ask_price1, pre_bid_price1):
"""获取成交的区域,根据当前tick的成交价和上个tick的ask和bid价格进行比对
return: order_forward_enum
"""
if TickAnalysis.float_bigger_equal(last_price, pre_ask_price1):
local_order_forward = order_forward_enum.UP
elif TickAnalysis.float_smaller_equal(last_price, pre_bid_price1):
local_order_forward = order_forward_enum.DOWN
else:
if TickAnalysis.float_bigger_equal(last_price, ask_price1):
local_order_forward = order_forward_enum.UP
elif TickAnalysis.float_smaller_equal(last_price, bid_price1):
local_order_forward = order_forward_enum.DOWN
else:
local_order_forward = order_forward_enum.MIDDLE
return local_order_forward
现在有了逻辑(3)和(4)之后,可以计算出真正的开平了,逻辑如下(5)
换手,向上:多换,红色
换手,向下:空换,绿色
换手,不变:未知换,白色
双开,向上:双开,红色
双开,向下:双开,绿色
双开,不变:双开,白色
......
平仓,向上:空平,红色
平仓,向下:多平,绿色
平仓,不变:未知平,白色
对应上面的6种开平(不带方向),3种方向组合,一共是得到18种开平情况(带方向)
代码如下:
tick_type_cal_dict = {
open_interest_delta_forward_enum.NONE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.NOCHANGE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.EXCHANGE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGELONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGESHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.EXCHANGEUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.OPENFWDOUBLE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.OPEN:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENLONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENSHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.OPENUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.CLOSEFWDOUBLE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEDOUBLE,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
open_interest_delta_forward_enum.CLOSE:
{
order_forward_enum.UP: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSESHORT,
tick_type_key_enum.TICKCOLOR: tick_color_enum.RED},
order_forward_enum.DOWN: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSELONG,
tick_type_key_enum.TICKCOLOR: tick_color_enum.GREEN},
order_forward_enum.MIDDLE: {tick_type_key_enum.TICKTYPE: tick_type_enum.CLOSEUNKOWN,
tick_type_key_enum.TICKCOLOR: tick_color_enum.WHITE}
},
}
4、对手单
最后讲一下对手单,关于对手单的计算我自己也有疑问,我就按照别人的思路先来说说。
先举一个例子,现在有现手24手,增仓-8手,性质是空平。现手即成交了24手,这是双边,单边即成交了12手,空平说明这12手是空单主动买入平仓,12手(单边)空平。 增仓-8说明双边共减持8手,那单边就是减持4手,即有4手是多头平仓,4手是空头平仓(这包括在12手空头主动平仓中)。所以对手单就是4手多头平仓,12-4=8手空头开仓。
公式如下:
设S是对手单中开平方向相同的操作,O是对手单中开平方向相反的操作。
S+O=volume_delta/2
S-O=abs(open_interest_delta )-volume_delta/2
解以上方程得到
S=abs(open_interest_delta )/2
O=volume_delta/2 - S
再举下面的例子可以验证一下公式:
现手 增仓 开平 对手单
44 +22 空开 从+22可知道仓差是由11手空开与11手多开影响的,另外就是11手空开与11手空平的空换,总的就是22空开,11多开,11空平
100 0 空换 50手空开与50手空平的空换
18 +12 多开 从+12可知仓差是由6手多开与6手空开形象的,另外就是3手多开与3手多平的多换,总的就是9多开,6空开,3多平
226 -30 多平 从-30可知仓差是由15手多平与15手空平影响的,另外就是98手多平98手的多开的换手-多换,总的就是113多开,98多平,15空平
100 0 多换 50手多开与50手多平的多换
100 +100 双开 50手多开与50手空开
100 -100 双平 50手多平与50手空平
代码如下
def get_order_combination(open_interest_delta, volume_delta):
"""根据成交量变化和持仓量的变化计算出对手单的组合
仓位变化方向相反的单
order_opposite
仓位变化方向相同的单
order_similar
"""
open_interest_delta = open_interest_delta if open_interest_delta > 0 else -open_interest_delta
order_similar = open_interest_delta / 2.0
order_opposite = volume_delta / 2.0 - order_similar
return int(order_opposite), int(order_similar)
下面一篇文章将会贴出根据API实现的C++代码和Python代码。
参考如下: