保证金率和手续费率都是程序化交易者非常关心的话题,保证金率涉及到开仓时账户资金的冻结和占用,撤单或平仓则会解冻和解占用。手续费率则是真正要付给期货公司的佣金,而且通常开仓,平昨和平今手续费还各有不同。
这里面各种各样的坑,比如有人反应期货公司有的按交易所保证金率收,有的按交易所两倍来收,这样同样的钱在有的期货公司够开2$,而在有的就只能开1手;手续费那更是收的五花八门,各种各样的都有。甚至还有人反应出现过实际收的和开户时说的不一样这种事。
其实这两个费率都是可以通过CTP API直接查询得到的,但这两个查询和其他查询(如查询合约,资金,结算单等)有点不一样,所以本篇单独讲一下。
一、 查询保证金率
官方文档中涉及到保证金率的接口好几个,新手开发看到经常一脸懵逼,不知道究竟哪个才是实际中用到的。这里我们先罗列一下相关的:
//请求查询合约保证金率
def ReqQryInstrumentMarginRate(self,
pQryInstrumentMarginRate: 'CThostFtdcQryInstrumentMarginRateField',
nRequestID: 'int') -> "int"
//查询合约的返回中会带每条合约的保证金率
def ReqQryInstrument(self,
pQryInstrument: 'CThostFtdcQryInstrumentField',
nRequestID: 'int') -> "int"
//请求查询交易所保证金率
def ReqQryExchangeMarginRate(self,
pQryExchangeMarginRate: 'CThostFtdcQryExchangeMarginRateField',
nRequestID: 'int') -> "int"
//请求查询交易所调整保证金率
def ReqQryExchangeMarginRateAdjust(self,
pQryExchangeMarginRateAdjust: 'CThostFtdcQryExchangeMarginRateAdjustField',
nRequestID: 'int') -> "int"
在实际交易中冻结和占用的计算其实是采用第一个查询函数ReqQryInstrumentMarginRate的返回结果。
而ReqQryInstrument中返回的保证金率通常是交易所保证金率,计算中并不用到。ReqQryExchangeMarginRate和ReqQryExchangeMarginRateAdjust查询得到的是交易所相关的保证金率,这也只在计算中间过程中会用到。
这里我们只讲实际计算中用到的ReqQryInstrumentMarginRate查询,其参数类型为CThostFtdcQryInstrumentMarginRateField,具体字段:
01必填字段
BrokerID //经纪公司代码
InvestorID //投资者代码
HedgeFlag //投机套保标志
前两者开户时可得到,投机套保标志一般投资者填投机就可以。注意这三个字段是一定要填的,不填的话返回值就为空。
02选填字段
InstrumentID //合约代码
如果InstrumentID填空,则返回客户当前持仓对应的合约保证金率,否则返回相应InstrumentID的保证金率。也就是说这个查询和其他查询不一样,如果什么都不填,是不会得到所有的合约保证金率的。
最后给出个查询保证金率的示例:
qryinfofield = api.CThostFtdcQryInstrumentMarginRateField()
qryinfofield.BrokerID='9999'
qryinfofield.InvestorID='000001'
qryinfofield.InstrumentID='rb2007'
qryinfofield.HedgeFlag = api.THOST_FTDC_HF_Speculation
tapi.ReqQryInstrumentMarginRate(qryinfofield,0)
二、 查询手续费率
查手续费的接口也有好几个,罗列如下:
//请求查询合约手续费率
def ReqQryInstrumentCommissionRate(self,
pQryInstrumentCommissionRate: 'CThostFtdcQryInstrumentCommissionRateField',
nRequestID: 'int') -> "int":
//请求查询报单手续费
Def ReqQryInstrumentOrderCommRate(self,
pQryInstrumentOrderCommRate: 'CThostFtdcQryInstrumentOrderCommRateField',
nRequestID: 'int') -> "int":
// 请求查询期权或做市商合约手续费函数这里就不罗列了...
在期货交易中,实际计算用到的只有个前面两个函数,其中第一个查询的是合约的手续费率,第二个查询的是报单申报手续费(就是每报撤一次单子都会收一笔费用),目前来说这是中金所特有的。
也就是说中金所的手续费分为两部分,包括交易手续费和申报费两部分,前者可以通过第一个查询函数查到,后者通过第二个查询函数得到。
两个查询函数的参数类型虽然不一样,但是字段填写方法是一致的,这里我们以ReqQryInstrumentCommissionRate为例讲解,参数类型为CThostFtdcQryInstrumentCommissionRateField,具体字段:
01必填字段
BrokerID //经纪公司代码
InvestorID //投资者代码
02选填字段
InstrumentID //合约代码
如果InstrumentID填空,则返回客户当前持仓对应的合约手续费率,否则返回相应InstrumentID的合约手续费率。和上面查询保证金率的逻辑一样。
查询结果返回值还需要注意几点:
- 以开仓为例,查询手续费返回结果中有两项关于开仓的字段:OpenRatioByMoney(开仓手续费率)和OpenRatioByVolume(开仓手续费),这是两种计算手续费的方法。实际计算时的开仓手续费公式为:
手续费 = 成交数量*(成交价*合约乘数*OpenRatioByMoney+OpenRatioByVolume)
- 有时查询某合约(例如IF2009)的手续费时,得到的是其对应品种(例如IF)的手续费。这是因为该品种下所有合约的手续费都是一样的,所以就直接将手续费设到品种级别了。
- 交易所的手续费率这里查不到,大家可以去交易所官网上看,通常在交易数据/结算参数中。要注意的是大商所手续费中有个短线开平仓的概念,其实就是指今开今平。
最后给出个查询手续费率的示例:
qryinfofield = api.CThostFtdcQryInstrumentCommissionRateField()
qryinfofield.BrokerID='9999'
qryinfofield.InvestorID='000001'
qryinfofield.InstrumentID='rb2007'
tapi.ReqQryInstrumentCommissionRate(qryinfofield,0)