TqSdk

简单易用的Python开源量化交易开发包

Easy, Yet powerful

  1. 立即获得从行情到交易的完整功能
  1. 鼓励 Quick & Simple 的用户代码风格
  • 用 20行左右代码 完成一个完整的交易策略程序
  • 所有行情及交易接口都返回 object refrence, 一次调用获取, 内容可自动更新, 无需查询
  • 策略代码按 线性逻辑 编写, 避免复杂的回调函数/状态机
  1. 搭配天勤终端获得更多功能
  • 通过 历史复盘 功能,在特定的历史场景测试您的程序,7*24小时可用
  • 在天勤终端中构建 自定义组合, 并获得组合的报价和K线数据
  • 提供委托单/成交/持仓情况监控的UI界面
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk import TqApi, TqSim

# 创建API实例. 需要指定交易帐号. 如果使用API自带的模拟功能可以指定为 TqSim
api = TqApi(TqSim())
# 获得上期所 cu1812 的行情引用,当行情有变化时 quote 中的字段会对应更新
quote = api.get_quote("SHFE.cu1812")

while True:
    # 调用 wait_update 等待业务信息发生变化,例如: 行情发生变化, 委托单状态变化, 发生成交等等
    api.wait_update()
    # 每当业务信息有变化时就输出 cu1812 的最新行情时间和最新价
    # 注意:其他合约的行情的更新也会触发业务信息变化,因此这里可能会将同一笔行情输出多次
    print(quote["datetime"], quote["last_price"])
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk import TqApi, TqSim
import datetime

api = TqApi(TqSim())
# 获得cu1812 tick序列的引用
ticks = api.get_tick_serial("SHFE.cu1812")
# 获得cu1812 10秒K线的引用
klines = api.get_kline_serial("SHFE.cu1812", 10)

while True:
    api.wait_update()
    # 判断整个tick序列是否有变化
    if api.is_changing(ticks):
        # ticks[-1]返回序列中最后一个tick
        print("tick变化", ticks[-1])
    # 判断最后一根K线的时间是否有变化,如果发生变化则表示新产生了一根K线
    if api.is_changing(klines[-1], "datetime"):
        # datetime: 自unix epoch(1970-01-01 00:00:00 GMT)以来的纳秒数
        print("新K线", datetime.datetime.fromtimestamp(klines[-1]["datetime"]/1e9))
    # 判断最后一根K线的收盘价是否有变化
    if api.is_changing(klines[-1], "close"):
        # klines.close返回收盘价序列
        print("K线变化", datetime.datetime.fromtimestamp(klines[-1]["datetime"]/1e9), klines.close[-1])

#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk import TqApi, TqSim

api = TqApi(TqSim())
# 获得 m1901 的持仓引用,当持仓有变化时 position 中的字段会对应更新
position = api.get_position("DCE.m1901")
# 获得资金账户引用,当账户有变化时 account 中的字段会对应更新
account = api.get_account()
# 下单并返回委托单的引用,当该委托单有变化时 order 中的字段会对应更新
order = api.insert_order(symbol="DCE.m1901", direction="BUY", offset="OPEN", volume=5)

while True:
    api.wait_update()
    if api.is_changing(order, ["status", "volume_orign", "volume_left"]):
        print("单状态: %s, 已成交: %d 手" % (order["status"], order["volume_orign"] - order["volume_left"]))
    if api.is_changing(position, "volume_long_today"):
        print("今多头: %d 手" % (position["volume_long_today"]))
    if api.is_changing(account, "available"):
        print("可用资金: %.2f" % (account["available"]))
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'chengzhi'

from tqsdk import TqApi, TqSim, TargetPosTask

'''
价差回归
当近月-远月的价差大于200时做空近月,做多远月
当价差小于150时平仓
'''
api = TqApi(TqSim())
quote_near = api.get_quote("SHFE.rb1810")
quote_deferred = api.get_quote("SHFE.rb1901")
# 创建 rb1810 的目标持仓 task,该 task 负责调整 rb1810 的仓位到指定的目标仓位
target_pos_near = TargetPosTask(api, "SHFE.rb1810")
# 创建 rb1901 的目标持仓 task,该 task 负责调整 rb1901 的仓位到指定的目标仓位
target_pos_deferred = TargetPosTask(api, "SHFE.rb1901")

while True:
    api.wait_update()
    if api.is_changing(quote_near) or api.is_changing(quote_deferred):
        spread = quote_near["last_price"] - quote_deferred["last_price"]
        print("当前价差:", spread)
        if spread > 200:
            print("目标持仓: 空近月,多远月")
            # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓
            target_pos_near.set_target_volume(-1)
            target_pos_deferred.set_target_volume(1)
        elif spread < 150:
            print("目标持仓: 空仓")
            target_pos_near.set_target_volume(0)
            target_pos_deferred.set_target_volume(0)
策略介绍请点这里, 完整代码请点这里
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
__author__ = 'limin'

from functools import reduce
from tqsdk import TqApi, TargetPosTask, TqSim

"""
网格交易算法
参考: https://xueqiu.com/6027474589/59766858
"""
# 网格计划参数:
symbol = "DCE.jd1901"  # 合约代码
start_price = 4047  # 起始价位
grid_amount = 10  # 网格在多头、空头方向的格子(档位)数量
grid_region_long = [0.005] * grid_amount  # 多头每格价格跌幅(网格密度)
grid_region_short = [0.005] * grid_amount  # 空头每格价格涨幅(网格密度)
grid_volume_long = [i for i in range(grid_amount + 1)]  # 多头每格交易手数
grid_volume_short = [i for i in range(grid_amount + 1)]  # 空头每格交易手数
grid_prices_long = [reduce(lambda p, r: p*(1-r), grid_region_long[:i], start_price) for i in range(grid_amount + 1)]  # 多头每格的触发价位列表
grid_prices_short = [reduce(lambda p, r: p*(1+r), grid_region_short[:i], start_price) for i in range(grid_amount + 1)]  # 空头每格的触发价位列表

print("起始价位:", start_price)
print("多头每格交易量:", grid_volume_long)
print("多头每格的价位:", grid_prices_long)
print("空头每格的价位:", grid_prices_short)

api = TqApi(TqSim())
quote = api.get_quote(symbol)  # 行情数据
target_pos = TargetPosTask(api, symbol)
position = api.get_position(symbol)  # 持仓信息


def wait_price(layer):
    """等待行情最新价变动到其他档位,则进入下一档位或回退到上一档位; 如果从下一档位回退到当前档位,则设置为当前对应的持仓手数;
        layer : 当前所在第几个档位层次; layer>0 表示多头方向, layer<0 表示空头方向 """ if layer > 0 or quote["last_price"] <= grid_prices_long[1]:  # 是多头方向
        while True:
            api.wait_update()
            # 如果当前档位小于最大档位,并且最新价小于等于下一个档位的价格: 则设置为下一档位对应的手数后进入下一档位层次
            if layer < grid_amount and quote["last_price"] <= grid_prices_long[layer + 1]: target_pos.set_target_volume(grid_volume_long[layer + 1]) print("时间:", quote["datetime"], "最新价:", quote["last_price"], "进入: 多头第", layer + 1, "档") wait_price(layer + 1) # 从下一档位回退到当前档位后, 设置回当前对应的持仓手数 target_pos.set_target_volume(grid_volume_long[layer + 1]) # 如果最新价大于当前档位的价格: 则回退到上一档位 if quote["last_price"] > grid_prices_long[layer]:
                print("时间:", quote["datetime"], "最新价:", quote["last_price"], "回退到: 多头第", layer, "档")
                return
    elif layer < 0 or quote["last_price"] >= grid_prices_short[1]:  # 是空头方向
        layer = -layer  # 转为正数便于计算
        while True:
            api.wait_update()
            # 如果当前档位小于最大档位层次,并且最新价大于等于下一个档位的价格: 则设置为下一档位对应的持仓手数后进入下一档位层次
            if layer < grid_amount and quote["last_price"] >= grid_prices_short[layer + 1]:
                target_pos.set_target_volume(-grid_volume_short[layer + 1])
                print("时间:", quote["datetime"], "最新价:", quote["last_price"], "进入: 空头第", layer + 1, "档")
                wait_price(-(layer + 1))
                # 从下一档位回退到当前档位后, 设置回当前对应的持仓手数
                target_pos.set_target_volume(-grid_volume_short[layer + 1])
            # 如果最新价小于当前档位的价格: 则回退到上一档位
            if quote["last_price"] < grid_prices_short[layer]:
                print("时间:", quote["datetime"], "最新价:", quote["last_price"], "回退到: 空头第", layer, "档")
                return


while True:
    api.wait_update()
    wait_price(0)  # 从第0层开始进入网格
    target_pos.set_target_volume(0)

Install

TqSdk可在Linux或Windows环境下安装使用。您需要先安装 Python 3.6+ ,再使用 pip 安装 TqSdk:
pip install tqsdk

Resource

Blogs