tqsdk.lib - 业务工具库

class tqsdk.lib.TargetPosTaskSingleton

TargetPosTask 需要保证在每个账户下每个合约只有一个 TargetPosTask 实例。

当用户多次调用时,应该保证对于同一账户同一合约使用相同的参数构造,否则抛错。

在修改 TargetPosTask 构造参数时,同时应该修改 TargetPosTaskSingleton.__call__ 方法的参数,要确保其个数、名称、默认值和文档描述一致, 这些参数才是实际传给 TargetPosTask.__init__ 方法的参数。

同时应该在 TargetPosTask 实例运行结束时释放相应的资源,_instances 需要情况对应的引用。

class tqsdk.lib.TargetPosTask(api, symbol, price='ACTIVE', offset_priority='今昨,开', min_volume=None, max_volume=None, trade_chan=None, account: Optional[Union[tqsdk.account.TqAccount, tqsdk.account.TqKq, tqsdk.sim.TqSim]] = None, *args, **kwargs)

目标持仓 task, 该 task 可以将指定合约调整到目标头寸

创建目标持仓task实例,负责调整归属于该task的持仓 (默认为整个账户的该合约净持仓).

注意:
  1. TargetPosTask 在 set_target_volume 时并不下单或撤单, 它的下单和撤单动作, 是在之后的每次 wait_update 时执行的. 因此, 需保证 set_target_volume 后还会继续调用wait_update()

  2. 请勿在使用 TargetPosTask 的同时使用 insert_order() 函数, 否则将导致 TargetPosTask 报错或错误下单。

  3. TargetPosTask 如果同时设置 min_volume(每笔最小下单手数),max_volume(每笔最大下单的手数)两个参数,表示采用 大单拆分模式 下单。

    大单拆分模式 下,每次下单的手数为随机生成的正整数,值介于 min_volume、max_volume 之间。

    具体说明:调用 set_target_volume 后,首先会根据目标持仓手数、开平仓顺序计算出,需要平今、平昨、开仓的目标下单手数及顺序。

    • 如果在调整持仓的目标下单手数小于 max_volume,则直接以目标下单手数下单。

    • 如果在调整持仓的目标下单手数大于等于 max_volume,则会以 min_volume、max_volume 之间的随机手数下一笔委托单,手数全部成交后,会接着处理剩余的手数; 继续以随机手数下一笔委托单,全部成交后,继续处理剩余的手数,直至剩余手数小于 max_volume 时,直接以剩余手数下单。

    当使用大单拆分模式下单时,必须同时填写 min_volume、max_volume,且需要满足 max_volume >= min_volume > 0。

Args:

api (TqApi): TqApi实例,该task依托于指定api下单/撤单

symbol (str): 负责调整的合约代码

price (str / Callable): [可选]下单方式, 默认为 "ACTIVE"。
  • "ACTIVE":对价下单,在持仓调整过程中,若下单方向为买,对价为卖一价;若下单方向为卖,对价为买一价。

  • "PASSIVE":对价下单,在持仓调整过程中,若下单方向为买,对价为买一价;若下单方向为卖,对价为卖一价。

  • Callable[[str], Union[float, int]]: 函数参数为下单方向,函数返回值是下单价格。如果返回 nan,程序会抛错。

offset_priority (str): [可选]开平仓顺序,昨=平昨仓,今=平今仓,开=开仓,逗号=等待之前操作完成

对于下单指令区分平今/昨的交易所(如上期所),按照今/昨仓的数量计算是否能平今/昨仓 对于下单指令不区分平今/昨的交易所(如中金所),按照“先平当日新开仓,再平历史仓”的规则计算是否能平今/昨仓

  • "今昨,开" 表示先平今仓,再平昨仓,等待平仓完成后开仓,对于没有单向大边的品种避免了开仓保证金不足

  • "今昨开" 表示先平今仓,再平昨仓,并开仓,所有指令同时发出,适合有单向大边的品种

  • "昨开" 表示先平昨仓,再开仓,禁止平今仓,适合股指这样平今手续费较高的品种

  • "开" 表示只开仓,不平仓,适合需要进行锁仓操作的品种

min_volume (int): [可选] 大单拆分模式下 每笔最小下单的手数,默认不启用 大单拆分模式

max_volume (int): [可选] 大单拆分模式下 每笔最大下单的手数,默认不启用 大单拆分模式

trade_chan (TqChan): [可选]成交通知channel, 当有成交发生时会将成交手数(多头为正数,空头为负数)发到该channel上

account (TqAccount/TqKq/TqSim): [可选]指定发送下单指令的账户实例, 多账户模式下,该参数必须指定

注意

当 price 参数为函数类型时,该函数应该返回一个有效的价格值,应该避免返回 nan。以下为 price 参数是函数类型时的示例。

Example1:

# ... 用户代码 ...
quote = api.get("SHFE.cu2012")
def get_price(direction):
    # 在 BUY 时使用买一价加一档价格,SELL 时使用卖一价减一档价格
    if direction == "BUY":
        price = quote.bid_price1 + quote.price_tick
    else:
        price = quote.ask_price1 - quote.price_tick
    # 如果 price 价格是 nan,使用最新价报单
    if price != price:
        price = quote.last_price
    return price

target_pos = TargetPosTask(api, "SHFE.cu2012", price=get_price)
# ... 用户代码 ...

Example2:

# ... 用户代码 ...
quote1 = api.get("SHFE.cu2012")
quote2 = api.get("SHFE.au2012")

def get_price(direction, quote):
    # 在 BUY 时使用买一价加一档价格,SELL 时使用卖一价减一档价格
    if direction == "BUY":
        price = quote.bid_price1 + quote.price_tick
    else:
        price = quote.ask_price1 - quote.price_tick
    # 如果 price 价格是 nan,使用最新价报单
    if price != price:
        price = quote.last_price
    return price

target_pos1 = TargetPosTask(api, "SHFE.cu2012", price=lambda direction: get_price(direction, quote1))
target_pos2 = TargetPosTask(api, "SHFE.au2012", price=lambda direction: get_price(direction, quote2))
# ... 用户代码 ...

Example3:

# 大单拆分模式用法示例

from tqsdk import TqApi, TqAuth, TargetPosTask
api = TqApi(auth=TqAuth("信易账户", "账户密码"))
position = api.get_position('SHFE.rb2106')

# 同时设置 min_volume、max_volume 两个参数,表示使用大单拆分模式
t = TargetPosTask(api, 'SHFE.rb2106', min_volume=2, max_volume=10)
t.set_target_volume(50)
while True:
    api.wait_update()
    if position.pos_long == 50:
        break
api.close()

# 说明:
# 以上代码使用 TqSim 交易,开始时用户没有 SHFE.cu2012 合约的任何持仓,那么在 t.set_target_volume(50) 之后应该开多仓 50 手
# 根据用户参数,下单使用大单拆分模式,每次下单手数在 2~10 之间,打印出的成交通知可能是这样的:
# 2021-03-15 11:29:48 -     INFO - 模拟交易成交记录
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.516138, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 7, 价格: 4687.000,手续费: 32.94
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.519699, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 8, 价格: 4687.000,手续费: 37.64
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.522848, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 10, 价格: 4687.000,手续费: 47.05
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.525617, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 8, 价格: 4687.000,手续费: 37.64
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.528151, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 7, 价格: 4687.000,手续费: 32.94
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.530930, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 7, 价格: 4687.000,手续费: 32.94
# 2021-03-15 11:29:48 -     INFO - 时间: 2021-03-15 11:29:47.533515, 合约: SHFE.rb2106, 开平: OPEN, 方向: BUY, 手数: 3, 价格: 4687.000,手续费: 14.12
set_target_volume(volume: int)None

设置目标持仓手数

Args:

volume (int): 目标持仓手数,正数表示多头,负数表示空头,0表示空仓

Example1:

# 设置 rb1810 持仓为多头5手
from tqsdk import TqApi, TqAuth, TargetPosTask

api = TqApi(auth=TqAuth("信易账户", "账户密码"))
target_pos = TargetPosTask(api, "SHFE.rb1810")
target_pos.set_target_volume(5)
while True:
    # 需在 set_target_volume 后调用wait_update()以发出指令
    api.wait_update()

Example2:

# 多账户模式下使用 TargetPosTask
from tqsdk import TqApi, TqMultiAccount, TqAuth, TargetPosTask

account1 = TqAccount("H海通期货", "123456", "123456")
account2 = TqAccount("H宏源期货", "654321", "123456")
api = TqApi(TqMultiAccount([account1, account2]), auth=TqAuth("信易账户", "账户密码"))
symbol1 = "DCE.m2105"
symbol2 = "DCE.i2101"
# 多账户模式下, 调仓工具需要指定账户实例
target_pos1 = TargetPosTask(api, symbol1, account=account1)
target_pos2 = TargetPosTask(api, symbol2, account=account2)
target_pos1.set_target_volume(30)
target_pos2.set_target_volume(80)
while True:
    api.wait_update()

api.close()
class tqsdk.lib.InsertOrderUntilAllTradedTask(api, symbol, direction, offset, volume, min_volume: Optional[int] = None, max_volume: Optional[int] = None, price: Union[str, Callable[[str], Union[float, int]]] = 'ACTIVE', trade_chan=None, account: Optional[Union[tqsdk.account.TqAccount, tqsdk.account.TqKq, tqsdk.sim.TqSim]] = None)

追价下单task, 该task会在行情变化后自动撤单重下,直到全部成交 (注:此类主要在tqsdk内部使用,并非简单用法,不建议用户使用)

创建追价下单task实例

Args:

api (TqApi): TqApi实例,该task依托于指定api下单/撤单

symbol (str): 拟下单的合约symbol, 格式为 交易所代码.合约代码, 例如 "SHFE.cu1801"

direction (str): "BUY" 或 "SELL"

offset (str): "OPEN", "CLOSE" 或 "CLOSETODAY"

volume (int): 需要下单的手数

min_volume (int): [可选] 大单拆分模式下 每笔最小下单的手数,默认不启用 大单拆分模式

max_volume (int): [可选] 大单拆分模式下 每笔最大下单的手数,默认不启用 大单拆分模式

price (str / Callable): [可选]下单方式, 默认为 "ACTIVE"。
  • "ACTIVE":对价下单,在持仓调整过程中,若下单方向为买,对价为卖一价;若下单方向为卖,对价为买一价。

  • "PASSIVE":对价下单,在持仓调整过程中,若下单方向为买,对价为买一价;若下单方向为卖,对价为卖一价。

  • Callable[[str], Union[float, int]]: 函数参数为下单方向,函数返回值是下单价格。如果返回 nan,程序会抛错。

trade_chan (TqChan): [可选]成交通知channel, 当有成交发生时会将成交手数(多头为正数,空头为负数)发到该channel上

account (TqAccount/TqKq/TqSim): [可选]指定发送下单指令的账户实例, 多账户模式下,该参数必须指定

class tqsdk.lib.InsertOrderTask(api, symbol, direction, offset, volume, limit_price=None, order_chan=None, trade_chan=None, account: Optional[Union[tqsdk.account.TqAccount, tqsdk.account.TqKq, tqsdk.sim.TqSim]] = None)

下单task (注:此类主要在tqsdk内部使用,并非简单用法,不建议用户使用)

创建下单task实例

Args:

api (TqApi): TqApi实例,该task依托于指定api下单/撤单

symbol (str): 拟下单的合约symbol, 格式为 交易所代码.合约代码, 例如 "SHFE.cu1801"

direction (str): "BUY" 或 "SELL"

offset (str): "OPEN", "CLOSE" 或 "CLOSETODAY"

volume (int): 需要下单的手数

limit_price (float): [可选]下单价格, 默认市价单

order_chan (TqChan): [可选]委托单通知channel, 当委托单状态发生时会将委托单信息发到该channel上

trade_chan (TqChan): [可选]成交通知channel, 当有成交发生时会将成交手数(多头为正数,空头为负数)发到该channel上

account (TqAccount/TqKq/TqSim): [可选]指定发送下单指令的账户实例, 多账户模式下,该参数必须指定