@@ -214,6 +214,33 @@ def get_price(direction):
214
214
self ._time_update_task = self ._api .create_task (self ._update_time_from_md ()) # 监听行情更新并记录当时本地时间的task
215
215
self ._local_time_record = time .time () - 0.005 # 更新最新行情时间时的本地时间
216
216
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__ ()
217
244
218
245
def set_target_volume (self , volume : int ) -> None :
219
246
"""
@@ -379,12 +406,7 @@ async def _target_pos_task(self):
379
406
all_tasks .append (order_task )
380
407
delta_volume -= order_volume if order_dir == "BUY" else - order_volume
381
408
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 )
388
410
389
411
def cancel (self ):
390
412
"""
@@ -423,6 +445,46 @@ def cancel(self):
423
445
424
446
api.close()
425
447
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
+
426
488
"""
427
489
self ._task .cancel ()
428
490
@@ -433,7 +495,10 @@ def is_finished(self) -> bool:
433
495
Returns:
434
496
bool: 当前 TargetPosTask 实例是否已经结束
435
497
"""
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
437
502
438
503
439
504
class InsertOrderUntilAllTradedTask (object ):
0 commit comments