问题描述
解决方案
在 QMT 量化交易平台中,按指定金额下单(order_value)和按指定股数下单(order_shares)是两种最常用的交易方式。它们的主要区别在于交易数量的计算逻辑和资金管理侧重点不同。
以下是详细的解释和代码示例。
1. 概念解释
按指定股数下单 (order_shares)
- 定义:直接指定要买入或卖出的股票数量(例如:买入 100 股,卖出 500 股)。
- 特点:
- 数量精确:成交的股数完全由用户指定。
- 资金不确定:所需资金取决于当前的股价。如果股价波动较大,实际占用的资金也会随之波动。
- 适用场景:策略逻辑是基于具体的持仓数量,或者需要精确控制手数时(如网格交易中每次固定买卖 1 手)。
按指定金额下单 (order_value)
- 定义:指定要花费多少资金买入,或者要套现多少资金卖出(例如:买入 1 万元的股票)。
- 特点:
- 资金可控:用户直接控制投入的资金量。
- 数量自动计算:系统会根据当前的股价(或指定的限价)自动计算出对应的股数。
- 自动取整:对于 A 股,系统会自动将计算出的股数向下取整到 100 的倍数(1 手)。因此,实际成交金额通常会略小于指定的金额。
- 适用场景:资产配置策略、轮动策略,或者希望每个标的分配固定金额(如等权重配置)时。
2. 代码示例
以下代码展示了如何在 QMT 策略中分别使用这两种方式进行下单。
# -*- coding: gbk -*-
def init(ContextInfo):
# 设置资金账号,请替换为您真实的资金账号
ContextInfo.accid = '6000000000'
# 设置股票池,这里以浦发银行(600000.SH)和平安银行(000001.SZ)为例
ContextInfo.set_universe(['600000.SH', '000001.SZ'])
# 定义一个全局变量,防止在回测或实时运行时重复下单
ContextInfo.has_ordered = False
def handlebar(ContextInfo):
# 获取当前 K 线位置
index = ContextInfo.barpos
# 获取当前时间戳
realtime = ContextInfo.get_bar_timetag(index)
# 仅在最后一根 K 线(实时行情或回测的当前帧)且未下单时执行
if ContextInfo.is_last_bar() and not ContextInfo.has_ordered:
# ---------------------------------------------------
# 示例 1:按指定股数下单 (order_shares)
# ---------------------------------------------------
stock_1 = '600000.SH' # 浦发银行
target_shares = 1000 # 计划买入 1000 股
# 下单函数:order_shares
# 参数 1: 股票代码
# 参数 2: 股数 (正数买入,负数卖出)
# 参数 3: 报价类型 (这里使用 'fix' 指定价,也可以用 'LATEST' 最新价等)
# 参数 4: 价格 (这里为了演示,假设以 10.5 元买入,实际应获取行情)
# 参数 5: ContextInfo 对象
# 参数 6: 资金账号
order_shares(stock_1, target_shares, 'fix', 10.5, ContextInfo, ContextInfo.accid)
print(f"【按股数下单】代码: {stock_1}, 目标股数: {target_shares}")
# ---------------------------------------------------
# 示例 2:按指定金额下单 (order_value)
# ---------------------------------------------------
stock_2 = '000001.SZ' # 平安银行
target_value = 50000 # 计划买入 50000 元市值的股票
# 下单函数:order_value
# 参数 1: 股票代码
# 参数 2: 金额 (正数代表买入花费的金额,负数代表卖出套现的金额)
# 参数 3: 报价类型 (这里使用 'LATEST' 最新价)
# 参数 4: 价格 (使用最新价时,此参数通常填 -1 或 0,系统会自动获取)
# 参数 5: ContextInfo 对象
# 参数 6: 资金账号
# 注意:系统会自动计算 50000 / 最新价,并向下取整到 100 的倍数
order_value(stock_2, target_value, 'LATEST', 0, ContextInfo, ContextInfo.accid)
print(f"【按金额下单】代码: {stock_2}, 目标金额: {target_value}")
# 标记已下单,避免重复执行
ContextInfo.has_ordered = True
3. 关键点总结
-
正负号含义:
order_shares:100代表买入 100 股,-100代表卖出 100 股。order_value:10000代表花费 10000 元买入,-10000代表卖出股票直到获得 10000 元现金(如果持仓不足以套现该金额,则卖出全部持仓)。
-
取整机制:
- 使用
order_value时,如果计算结果是 1560 股,QMT 会自动将其调整为 1500 股(A 股买入必须是 100 的整数倍)。因此,实际成交金额通常小于等于目标金额。
- 使用
-
资金检查:
- 这两个函数在发送订单前都会进行本地资金或持仓检查。如果资金不足(对于买入)或持仓不足(对于卖出),API 将不会创建发送订单。
Q&A
Q: 如果使用 order_value 买入,计算出的股数不足 1 手(100股)会发生什么?
A: 如果指定的金额除以股价后不足 100 股,QMT 通常会向下取整为 0,即不会发出任何委托,因为 A 股买入最小单位为 1 手。
Q: order_shares 和 order_value 支持回测吗?
A: 支持。这两个函数在回测模式和实盘模式下均可使用。在回测中,它们会根据历史 K 线数据进行撮合;在实盘中,它们会发送真实的交易指令。
Q: 如何以市价单(不指定价格)进行按金额买入?
A: 可以将 style 参数设置为 'MARKET'(市价)或 'LATEST'(最新价),并将 price 参数设置为 0 或 -1。例如:order_value('600000.SH', 10000, 'LATEST', 0, ContextInfo, accId)。