@@ -214,6 +214,33 @@ def get_price(direction):
214214 self ._time_update_task = self ._api .create_task (self ._update_time_from_md ()) # 监听行情更新并记录当时本地时间的task
215215 self ._local_time_record = time .time () - 0.005 # 更新最新行情时间时的本地时间
216216 self ._local_time_record_update_chan = TqChan (self ._api , last_only = True ) # 监听 self._local_time_record 更新
217+ self ._wait_task_finished = self ._api ._loop .create_future ()
218+ self ._task .add_done_callback (lambda _ : self ._api .create_task (self ._exit_task ()))
219+
220+ async def _exit_task (self ):
221+ """
222+ 执行 task.cancel() 时, 删除掉该 symbol 对应的 TargetPosTask 实例,以释放占有的资源。
223+
224+ 当用户代码为:
225+ t = TargetPosTask(api, 'SHFE.rb2106', min_volume=2, max_volume=10)
226+ t.cancel()
227+ await asyncio.gather(t._task, return_exceptions=True)
228+
229+ 以上代码执行后,t._task 中的 finally 部分没有被执行过,因为 t._task 本身从来没有被执行过。
230+
231+ 所以这里用 add_done_callback 的方式,处理 __init__ 方法中创建的资源。
232+ self._task、self._pos_chan、self._time_update_task 都是在 __init__ 方法里创建的资源,所以在这里释放资源,
233+ self._task 中的 finally 部分只处理在 self._task 函数里创建的资源。
234+ """
235+ # self._account 类型为 TqSim/TqKq/TqAccount,都包括 _account_key 变量
236+ TargetPosTaskSingleton ._instances .pop (self ._account ._account_key + "#" + self ._symbol , None )
237+ await self ._pos_chan .close ()
238+ self ._time_update_task .cancel ()
239+ await asyncio .gather (self ._time_update_task , return_exceptions = True )
240+ self ._wait_task_finished .set_result (True )
241+
242+ def __await__ (self ):
243+ return self ._wait_task_finished .__await__ ()
217244
218245 def set_target_volume (self , volume : int ) -> None :
219246 """
@@ -379,12 +406,7 @@ async def _target_pos_task(self):
379406 all_tasks .append (order_task )
380407 delta_volume -= order_volume if order_dir == "BUY" else - order_volume
381408 finally :
382- # 执行 task.cancel() 时, 删除掉该 symbol 对应的 TargetPosTask 实例
383- # self._account 类型为 TqSim/TqKq/TqAccount,都包括 _account_key 变量
384- TargetPosTaskSingleton ._instances .pop (self ._account ._account_key + "#" + self ._symbol , None )
385- await self ._pos_chan .close ()
386- self ._time_update_task .cancel ()
387- await asyncio .gather (* ([t ._task for t in all_tasks ] + [self ._time_update_task ]), return_exceptions = True )
409+ await asyncio .gather (* [t ._task for t in all_tasks ], return_exceptions = True )
388410
389411 def cancel (self ):
390412 """
@@ -423,6 +445,46 @@ def cancel(self):
423445
424446 api.close()
425447
448+
449+ Example2::
450+
451+ # 在异步代码中使用
452+ from datetime import datetime, time
453+ from tqsdk import TqApi, TargetPosTask
454+
455+ api = TqApi(auth=TqAuth("快期账户", "账户密码"))
456+ quote = api.get_quote("SHFE.rb2110")
457+
458+ async def demo(SYMBOL):
459+ quote = await api.get_quote(SYMBOL)
460+ target_pos_passive = TargetPosTask(api, SYMBOL, price="PASSIVE")
461+ async with api.register_update_notify() as update_chan:
462+ async for _ in update_chan:
463+ if datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f").time() < time(14, 50):
464+ # ... 策略代码 ...
465+ else:
466+ target_pos_passive.cancel() # 取消 TargetPosTask 实例
467+ await target_pos_passive # 等待 target_pos_passive 处理 cancel 结束
468+ break
469+
470+ target_pos_active = TargetPosTask(api, "SHFE.rb2110", price="ACTIVE")
471+ target_pos_active.set_target_volume(0) # 平所有仓位
472+ pos = await api.get_position(SYMBOL)
473+ async with api.register_update_notify() as update_chan:
474+ async for _ in update_chan:
475+ if pos.pos == 0:
476+ target_pos_active.cancel() # 取消 TargetPosTask 实例
477+ await target_pos_active # 等待 target_pos_active 处理 cancel 结束
478+ break
479+
480+
481+ symbol_list = ["SHFE.rb2107", "DCE.m2109"] # 设置合约代码
482+ for symbol in symbol_list:
483+ api.create_task(demo("SHFE.rb2107")) # 为每个合约创建异步任务
484+
485+ while True:
486+ api.wait_update()
487+
426488 """
427489 self ._task .cancel ()
428490
@@ -433,7 +495,10 @@ def is_finished(self) -> bool:
433495 Returns:
434496 bool: 当前 TargetPosTask 实例是否已经结束
435497 """
436- return self ._task .done ()
498+ if self ._wait_task_finished .done ():
499+ assert self ._task .done () is True
500+ return self ._wait_task_finished .result ()
501+ return False
437502
438503
439504class InsertOrderUntilAllTradedTask (object ):
0 commit comments