updatebyprimarykeyselective怎么更新某个字段为null_CTP程序化交易入门系列之十二:持仓的查询与更新(上)...

f2c449642cc1bf2a272bac95d7477833.png

持仓风控是程序化交易的必备风控之一,而持仓风控准确的前提是自己的交易系统要有准确的初始持仓及准确的后续更新持仓更新规则。

一般启动交易系统会做一系列初始化的操作,其中重要的一步便是获取该账号的当前持仓状况,这只能通过查询CTP得到。而后续的交易过程中如果有报单或者成交,就会有相应的持仓冻结及仓位变化,由于CTP的查询流控及为了确保仓位更新的实时性,我们一般会自己根据相应回报去更新仓位状态(当然如果是趋势性策略不在乎一丁点延时,直接去查询CTP而省去麻烦的更新也可以),这就涉及到一定的更新规则。

这一篇我们先从初始持仓的查询讲起。

一、持仓查询请求

请求查询持仓的函数为:

///请求查询投资者持仓
def ReqQryInvestorPosition(self, pQryInvestorPosition: 'CThostFtdcQryInvestorPositionField', nRequestID: 'int') -> "int":

其中参数类型为CThostFtdcQryInvestorPositionField,具体字段:

01 无必填字段

这个查询的参数是可以什么都不填的,如果什么都不填去查询则返回的是当前账户的所有持仓记录。但是要注意什么都不填不是说参数直接写个NULL或None就行,具体参考下面的示例。

02 选填字段

InstrumentID //合约代码

如果只想查某个合约的持仓,那只填这个字段就可以了。

这里分别给出查询当前账户所有持仓及某个合约持仓的示例:

  1. 查询所有持仓
//C++:
CThostFtdcQryInvestorPositionField qrypositionfield = {0};
m_pTradeApi->ReqQryInvestorPosition(&qrypositionfield, 0);

#Python:
qrypositionfield = api.CThostFtdcQryInvestorPositionField()
tradeapi.ReqQryInvestorPosition(qrypositionfield,0)

2. 查询单一合约的持仓

qrypositionfield = api.CThostFtdcQryInvestorPositionField()
qrypositionfield.InstrumentID="ag2012"
tradeapi.ReqQryInvestorPosition(qrypositionfield,0)

二、 持仓查询返回

对应的查询结果返回函数为:

///请求查询投资者持仓响应
virtual void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};

下面分别讲解各个参数。

01 pInvestorPosition

返回结果在第一个参数中pInvestorPosition中,参数类型为CThostFtdcInvestorPositionField,具体结果我们分部解释下:

  1. 持仓记录键值
///合约代码
InstrumentID;
///经纪公司代码
BrokerID;
///投资者代码
InvestorID;
///持仓多空方向
PosiDirection;
///投机套保标志
HedgeFlag;
///持仓日期
PositionDate;

开头这6个字段我们称之为持仓记录的键值(Key),通过这6个字段就可以区分唯一一条持仓记录。

  • InstrumentID记录的是合约ID,例如通过这个字段可以区分究竟是au2012的持仓还是ag2012的持仓记录。
  • PosiDirection是枚举值,'2'表示多头持仓;'3'表示空头持仓,可见同一合约的不同方向的持仓在CTP是通过不同的记录来返回的。
  • HedgeFlag是投机套保标志枚举值,多数投资者是'1',表示为投机仓。
  • PositionDate是区分是否历史仓的枚举值,‘1’表示当前交易日持仓;‘2’表示是历史仓(昨仓)。只有上期/能源交易所的合约才可能有PositionDate为‘2’的持仓记录,因为上期/能源区分今仓和昨仓记录,昨仓平仓需要单独指定平昨仓。

经过上面分析,对于个人投资者关键键值字段为合约,方向,持仓日期这3个,有这3个基本就能确定唯一持仓。

2. 持仓数量

///上日持仓
YdPosition;
///今日持仓
Position;
///今日持仓
TodayPosition;
  • Position是当前键值下的总持仓,随着客户开仓平仓而变动
  • TodayPosition是当前键值下的今日新持仓数量,随着客户开仓平今而变动
  • YdPosition是当前键值下的昨仓,需要注意:

1). 这是一个静态值,为当前交易日开始时客户该合约的历史仓位,并不会随着客户平昨仓而减小;

2). 当前真实的昨仓值为Position-TodayPosition;

3). 对于非上期/能源的交易所,合约的昨仓YdPosition和今仓TodayPosition在一条记录里面,而上期/能源是分成了两条记录。

下面针对第1和2部分我们举例说明:

94b401f43e5f0ae5557f0cbb4e9397bb.png

上面4条是SHFE的zn2011合约,上期/能源所将今昨仓是分为两条记录的,根据上面的键值组合普通投资者最多可能有4条记录。按PositionDate可以区分出前面2条是今仓,后面2条是昨仓。按PosiDirection可以区分第1条是空头持仓,第2条是多头持仓。

对于前2条zn2011的今仓,其中YdPosition字段为0;Position=TodayPosition随今天开仓及平今而波动。

后2条zn2011的昨仓,其中YdPosition字段为16,表示这个交易日开始时持有zn2011的昨仓16;空头Position为4,表示此时昨仓还剩下4手;TodayPosition为0,因为对于昨仓只可能有平昨操作,不可能在此记录上开新今仓。

最后2条是DCE的a2101合约,非上期/能源所今昨仓在一条记录里面,根据键值组合普通投资者最多可能有2条记录。按PosiDirection可以区分第1条是空头持仓,第2条是多头持仓。PositionDate只可能为1。

空头持仓中YdPosition字段为14,表示这个交易日开始时持有a2101的昨仓14;Position为26,表示此时仓位为26手;TodayPosition为25,表示此时今仓有25手,所以现在昨仓还剩下26-25=1手。

3. 冻结仓位

///多头冻结
LongFrozen;
///空头冻结
ShortFrozen;

冻结是指已报单但未成交的数量,对于多头持仓,多头冻结是指新开多头未成交的数量,空头冻结是指平多头仓位报单未成交的数量;空头持仓与之相反。

4. 其他字段

因为字段内容实在太多,这里挑一些大家常问到的讲一讲,其他的大家可以自己去实践反推。

///开仓量,当天该键值上总的开仓量
OpenVolume;    
///平仓量, 当天该键值上总的平仓量
CloseVolume;   
///持仓成本, 当天新开仓按开仓价计算,昨仓则是用昨结算价计算,计算公式为price*volume*RateMultiple
PositionCost;     
///开仓成本, 新老仓都是按照开仓价计算的成本,如果无昨仓与持仓成本字段是相同的值
OpenCost;
///平仓盈亏, 等于下面的逐日盯市平仓盈亏 
CloseProfit; 
///持仓盈亏, 按最新价计算出来的持仓值与持仓成本的差值
PositionProfit; 
///逐日盯市平仓盈亏,  昨仓是平仓价与昨结算价计算出的盈亏,今仓是平仓价与开仓价计算出的盈亏 ,计算公式为(closeprice - openprice或preSettlementPrice)*volume*RateMultiple
CloseProfitByDate;   
///逐笔对冲平仓盈亏, 平仓价与开仓价计算出的盈亏
CloseProfitByTrade;  
///保证金率,  该合约的交易保证金率,同查询所得值一致。昨仓无此值。
MarginRateByMoney; 
///保证金率(按手数), 该合约的交易保证金率(按手数),同查询所得值一致。昨仓无此值。
MarginRateByVolume;

02 pRspInfo

为NULL空指针,无用。

03 nRequestID

与请求函数中客户填写的nRequestID值一致,是为了将查询结果与请求对应起来。

04 bIsLast

bool变量,用于判断是否是最后一条查询结果。上面讲过,如果客户有多条持仓记录的话会多次回调函数返回结果,那如何判断所有的结果都已经回调给客户了呢?就是通过bIsLast判断。当bIsLast是true的时候表示该次回调为这次查询的最后一条结果。

三、其他常见问题

1. 没有开仓均价字段,可以自己计算。公式为开仓均价=开仓成本/持仓手数

2. 没有持仓均价字段,同样自己计算。公式为持仓均价=持仓成本/持仓手数

3. 如果相应键值上当天开仓并全部平仓,或者仅是报单未成交。依然可以查到相应的持仓数据,其中position字段为0,其他字段有相应的值。

4.如果客户有多条持仓记录的话,API会多次回调该函数,每次返回一条持仓记录,根据bIsLast判断是否最后一条。

5. 如果查询时客户没有任何持仓记录,API也会回调该函数。只是pInvestorPosition指针为空,bIsLast字段为true。

6. 有时候客户自己没有报组合仓却在查询中得到组合持仓的记录,如下最后一条:

105f0a5579748f38d8d1fdeb8a27b510.png

这是因为按有的交易所规则,盘后会自动将客户的相应持仓进行组合(组合规则有好几种),组合后会只收大单边的保证金,减少客户保证金占用,所以就多出来这条组合仓。组合仓记录会有对应的单边持仓记录,见上面两条记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值