经常有这样的疑问:
1. 1.为什么我明明下单了,但是在交易记录中却找不到?
2. 2.为什么我用获取到的order对象(实际上是None)查看order信息,总是报错 ` 'NoneType' object has no attribute XXX`?
3. 3.期货应该如何下单,以及如何平仓呢?
4. 4.为什么总是提示我下单数量为0?
如果对撮合的结果有疑惑,建议不要设置日志级别(也就是注释掉log.set_level) , 在每个下单函数前打印相关变量,对照日志查看下具体原因。
希望这篇帖子能帮助您解决您的疑惑。
# 可用于下单的函数:
****
* 注意!这四个函数是有区别的,下边用红色字体标出 *
* 注意!这里没有考虑滑点,关于滑点对成交价的影响:https://www.joinquant.com/post/16439 *
## (1) order(security, amount,...)
**按股(手)数下单**
将仓位中的股票数量调整至目标数量比较容易理解,直接下多少股/手的单
* 示例:
* order('000001.XSHE',100) 买进100股平安银行
* order('000001.XSHE',-100) 卖出100股平安银行,如果没有仓位,会有相关的warning
* order('000001.XSHE',99) 下单数不足一手,调整为0股,订单取消,返回None,会有相关的warning
* order('IF1901',10,side='long') 开多10手IF1901 默认side='long',所以当开多仓或者平多仓时可以不指定side
* order('IF1901',-5,side='short') 平空5手IF1901,如果空仓仓位不足5手,则平掉所有空仓,有相关warning
## (2) order_target(security, amount, ...)
**按目标股(手)数下单**
将仓位中的标的数量调整至目标数量,比如下单前仓位中有500股平安银行,如果使用order_target('000001.XSHE',100
* 股票示例(假设下单前已经持有了平安银行500股且全部可平仓):
* order_target('000001.XSHE',700) 调整平安银行的持股数至700股,也就是再买入200股平安银行
* order_target('000001.XSHE',200) 调整平安银行的持股数至200股,也就是卖出300股平安银行
* order_target('000001.XSHE',500) 目标数量已满足,不再调整
* 注:当value为0时,即时有不足100股的股票,也会全部进行平仓
* 期货示例(假设下单前已经持有了IF1901空单5手,多单3手)
* order_target('IF901.CCFX',2,side='long') 调整多单仓位至2手,之前已经有3手多单,所以平掉一手多单
* order_target('IF901.CCFX',7,side='short') 调整空单仓位至7手,之前已经有5手空单,所以在开2手空单
* order_target('IF901.CCFX',5,side='short') 空单仓位数量已经满足,不再调整,不会创建order对象,返回None,会有相关日志输出
## (3) order_value(security, value, ....)
**按价值/保证金下单**
按照标的的价值(期货为保证金)进行下单,会根据下单的value调整交易的数量,当下单的手数不足一手的整数倍时,向下调整至一手的整数倍
* 股票示例(假设平安银行下单时最新价为10元):
* order_value('000001.XSHE',10000) 10000/10 = 1000股 ,买入平安银行1000股
* order_value('000001.XSHE',750) 7500/10 = 750股,调整为700股,买入平安银行700股
* order_value('000001.XSHE',999) 999/10 = 99.9股,调整为0股,不会创建order对象,返回None,会有相关日志输出
* order_value('000001.XSHE',-2000) -2000/10 = -200 股,等同于order('000001.XSHE',-200)
* 期货部分
* 期货是保证金交易,下边将单独进行讲解期货的order_value和order_target_value
## (4) order_target_value(security, value, ...)
** 按目标价值/保证金下单**
可以参考order_value和order_target,按照满足标的在仓位中的目标价值下单,会根据下单的value和已有的仓位调整下单手数,不足一手的整数倍时,向下调整为一手的整数倍
* 股票示例(假设目前已持有平安银行500股且全部可平仓,下单时最新价为10元):
* order_target_values('000001.XSHE',10000) 10000/10 = 1000股,也就是再买入500股平安银行
* order_target_values('000001.XSHE',5000) 5000/10 = 500股,目标数量已满足,不会创建order对象,返回None,会有相关日志输出
* order_target_values('000001.XSHE',5999) 5999/10 = 599.9股,调整为500股,目标数量已满足,不会创建order对象,返回None,会有相关日志输出
* order_target_values('000001.XSHE',3550) 3550/10 = 355股,应当卖出145股,调整为100股,卖出100股平安银行
* 注:当value为0时,即时有不足100股的股票,也会全部进行平仓
****
## 期货部分
注意!期货是保证金交易 ,所以策略中涉及到的starting_cash,available_cash(可用资金)等是指的是可用于交易的保证金,下单所消耗的也是这些可用保证金。而order_value,order_target_value中的value参数也指的是消耗保证金 ,而不是标的资产的价值!
***
* 情景1:
* 比如说,使用order_value('CU1903.XSGE',10000000*0.05), [设置保证金比例](https://www.joinquant.com/help/api/help?name=api#set_slippage)为0.05,CU合约乘数为5。
当前CU1903.XSGE为47690点,则会下单 int(10000000/(47690×5))= 41手
* 情景2:已经持仓价值为1000万的股票,现在想使用等规模的IF1901货进行对冲,那么 value = 1000万×保证金比例(股指期货默认0.15)
* order_target_value('IF1901.CCFX',1000000*0.15,side='short')
* 计算方法:假设当前时刻IF1901的价格为3000点(IF合约乘数为300)
1000万/(3000点*300) = 11.11 ,向下取整为11手,也就是下11手的空单,如果空单仓位中已经有底仓,调整方式和股票相同
期货部份下单计算的策略演示demo文末回测
****
## 关于下单函数中的其他参数
### style 设置下单的类型
* MarketOrderStyle() 下市价单,默认 style = MarketOrderStyle()
* LimitOrderStyle(P) 下限价单,买入时价格不得高于P,卖出时价格不得低于P(期货开平空逻辑和开平多逻辑相反)
* 按天回测中,由于都是使用天bar线撮合,所以下限价单时,如果当前价不满足限价+滑点,那么都是盘后才成交,盘中仓位及成交信息不会进行更新,15:00后才会进行更新,所以限价单建议使用分钟频率。
* 限价单并不是以一个指定的价格成交,而是以等于或者低于设置的委托价的价格成交
示例:
```
order('000001.XSHE', 100) # 下一个市价单
order('000001.XSHE', 100, MarketOrderStyle()) # 下一个市价单, 功能同上
order('000001.XSHE', 100, LimitOrderStyle(10.0)) # 以10块价格下一个限价单
```
### side 设置下单多空方向
* side = 'long' 开/平多仓,默认为'long'
* side = 'short' 开/品空仓,股票,基金不能开空
* 注意,我们不会主动帮您将多空直接对冲掉,而是在long_position和short_position中分别操作,side也是分别对这两个仓位进行操作。
比如您之前仓位中有IF1901十手多单,现在如果下一个order('IF1901.CCFX',10,side='short'),那么long_position和short_position中将各自有一个10手的单,而不是将IF1901的多单对冲掉
### pindex 指定仓位
* 在使用[set_subportfolios](https://www.joinquant.com/help/api/help?name=api#策略组合操作)创建了多个仓位时,指定subportfolio 的序号, 从 0 开始, 比如 0 指定第一个 subportfolio, 1 指定第二个 subportfolio,默认为0。
### close_today 是否优先平今仓
平今字段,仅对上海国际能源中心,上海期货交易所,中金所生效,其他交易所将会报错(其他交易所没有区分平今与平昨,均按照先开先平的方法处理)。
* 对上海国际能源中心,上海期货交易所,中金所的标的:
close_today = True, 只平今仓
close_today = False, 优先平昨仓,昨仓不足部分平进仓
# 为什么已经下单了,却没有成交?
可能失败的原因:
* 1.使用order_target或者order_target_value,经过调整后目标数量已满足,不再下单,交易函数返回None
* 2.可用资金不足,调整后不足一手,不再下单,交易函数返回None
* 3.股票停牌,交易函数返回None
* 4.股票未上市或者退市,交易函数返回None
* 5.股票不存在/代码错误(注意代码的后缀,另外平台不提供05年之前已经退市的股票数据),交易函数返回None
* 6.为股票、基金开了空单,交易函数返回None
* 7.选择了不存在的仓位号,如没有建立多个仓位,而设定pindex的数大于0,交易函数返回None
* 8.限价单未满足(注意滑点对于限价单的影响),返回order对象,在未成交之前订单状态为open
* 9. 使用下单函数时,本身下的单就是0手,多打印下相关参数
* 10.为了避免以不合理的价格对标的进行下单,模拟盘在下单时会检查开盘(9:25)到下单时刻的累积成交量,若为0则会拒绝,提示:WARNING - 该标的截至到目前成交量为0 ,暂时无法成交。
注意:
当订单直接变为废单时,下单函数会返回None而不是order对象,此时直接调用order对象的属性会引发报错`'NoneType' object has no attribute "XXX"`
解决方法:
```
Order = order('000001.XSHE',1000)
if not Order:
print('下单失败')
if Order:
print(Order.filled) #打印已成交数量
```
## 注意:
因为下列原因, 有时候实际买入或者卖出的股票数量跟您设置的不一样,这个时候我们会在您的log中添加警告信息。
* 买入时会根据您当前的现金来限制您买入的数量
* 卖出时会根据您持有股票的数量来限制您卖出的数量
* 我们会遵守A股交易规则: 每次交易数量只能是100的整数倍, 但是卖光所有股票时不受这个限制
根据交易所规则, 每天结束时会取消所有未完成交易