#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'chengzhi' from tqsdk.api import TqApi api = TqApi("SIM") # 获得 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.api import TqApi api = TqApi("SIM") # 获得 cu1812 的持仓引用,当持仓有变化时 position 中的字段会对应更新 position = api.get_position("SHFE.cu1812") # 获得资金账户引用,当账户有变化时 account 中的字段会对应更新 account = api.get_account() # 下单并返回委托单的引用,当该委托单有变化时 order 中的字段会对应更新 order = api.insert_order(symbol="SHFE.cu1812", 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"]))
def twap_table(api: TqApi, symbol: str, target_pos: int, duration: int, min_volume_each_step: int, max_volume_each_step: int, account: Optional[Union[TqAccount, TqKq, TqSim]] = None): """ 返回基于 twap 策略的计划任务时间表。下单需要配合 TargetPosScheduler 使用。 Args: api (TqApi): TqApi实例,该task依托于指定api下单/撤单 symbol (str): 拟下单的合约 symbol, 格式为 交易所代码.合约代码, 例如 "SHFE.cu1801" target_pos (int): 目标持仓手数 duration (int): 算法执行的时长,以秒为单位,时长可以跨非交易时间段,但是不可以跨交易日 * 设置为 60*10, 可以是 10:10~10:15 + 10:30~10:35 min_volume_each_step (int): 调整持仓手数最小值,每步调整的持仓手数默认在最小和最大值中产生 max_volume_each_step (int): 调整持仓手数最大值,每步调整的持仓手数默认在最小和最大值中产生 account (TqAccount/TqKq/TqSim): [可选]指定发送下单指令的账户实例, 多账户模式下,该参数必须指定 Returns: pandas.DataFrame: 本函数返回一个 pandas.DataFrame 实例. 表示一份计划任务时间表。每一行表示一项目标持仓任务,包含以下列: + interval: 当前这项任务的持续时间长度,单位为秒 + target_pos: 当前这项任务的目标持仓 + price: 当前这项任务的下单价格模式,支持 PASSIVE(排队价),ACTIVE(对价),None(不下单,表示暂停一段时间) Example1:: from tqsdk import TqApi, TargetPosScheduler from tqsdk.algorithm import twap_table api = TqApi(auth="信易账户,用户密码") quote = api.get_quote("CZCE.MA109") # 设置twap任务参数 time_table = twap_table(api, "CZCE.MA109", -100, 600, 1, 5) # 目标持仓 -100 手,600s 内完成 print(time_table.to_string()) target_pos_sch = TargetPosScheduler(api, "CZCE.MA109", time_table) # 启动循环 while not target_pos_sch.is_finished(): api.wait_update() api.close() Example2:: from tqsdk import TqApi, TargetPosScheduler from tqsdk.algorithm import twap_table api = TqApi(auth="信易账户,用户密码") quote = api.get_quote("CZCE.MA109") # 设置 twap 任务参数, time_table = twap_table(api, "CZCE.MA109", -100, 600, 1, 5) # 目标持仓 -100 手,600s 内完成 # 定制化调整 time_table,例如希望第一项任务延迟 10s 再开始下单 # 可以在 time_table 的头部加一行 time_table = pandas.concat([ DataFrame([[10, 10, None]], columns=['interval', 'target_pos', 'price']), time_table ], ignore_index=True) target_pos_sch = TargetPosScheduler(api, "CZCE.MA109", time_table) while not target_pos_sch.is_finished(): api.wait_update() # 获取 target_pos_sch 实例所有的成交列表 print(target_pos_sch.trades_df) # 利用成交列表,您可以计算出策略的各种表现指标,例如: average_trade_price = sum(scheduler.trades_df['price'] * scheduler.trades_df['volume']) / sum(scheduler.trades_df['volume']) print("成交均价:", average_trade_price) api.close() """ account = api._account._check_valid(account) if account is None: raise Exception(f"多账户模式下, 需要指定账户实例 account") min_volume_each_step = int(min_volume_each_step) max_volume_each_step = int(max_volume_each_step) if max_volume_each_step <= 0 or min_volume_each_step <= 0: raise Exception( "请调整参数, min_volume_each_step、max_volume_each_step 必须是大于 0 的整数。") if min_volume_each_step > max_volume_each_step: raise Exception( "请调整参数, min_volume_each_step 必须小于 max_volume_each_step。") pos = api.get_position(symbol, account) target_pos = int(target_pos) delta_pos = target_pos - pos.pos volume = abs(delta_pos) # 总的下单手数 # 得到有效的手数序列和时间间隔序列 if volume < max_volume_each_step: interval_list, volume_list = [duration], [volume] else: volume_list = _gen_random_list(sum_val=volume, min_val=min_volume_each_step, max_val=max_volume_each_step) interval = int(duration / len(volume_list)) if interval < 3: raise Exception("请调整参数, 每次下单时间间隔不能小于3s, 将单次下单手数阈值调大或者增长下单时间。") min_interval = int(max(3, interval - 2)) max_interval = int(interval * 2 - max(3, interval - 2)) + 1 interval_list = _gen_random_list(sum_val=duration, min_val=min_interval, max_val=max_interval, length=len(volume_list)) time_table = DataFrame(columns=['interval', 'volume', 'price']) for index, volume in enumerate(volume_list): assert interval_list[index] >= 3 active_interval = 2 append_time_table = pd.DataFrame([{ "interval": interval_list[index] - active_interval, "volume": volume, "price": "PASSIVE" }, { "interval": active_interval, "volume": 0, "price": "ACTIVE" }]) time_table = pd.concat([time_table, append_time_table], ignore_index=True) time_table['volume'] = time_table['volume'].mul(-1 if delta_pos < 0 else 1) time_table['target_pos'] = time_table['volume'].cumsum() time_table['target_pos'] = time_table['target_pos'].add(pos.pos) time_table.drop(columns=['volume'], inplace=True) time_table = time_table.astype({ 'target_pos': 'int64', 'interval': 'float64' }) return time_table