Skip to content

日志和只跑一次:日期戳 / C.done

这是工程记录。handlebar 每根 K 线都会进。不卡住,同一天会把接口打几十遍。不构成投资建议,不代操盘。

为什么要戳

场景不戳会怎样
日线 handlebar回测每天一根还好;实盘同一分钟可能进多次
分钟线一天几百根,选股、查持仓、写文件会重复
run_time 秒级更容易连打
下单 / 申购 / 撤单重复提交

长期状态不要只塞在 ContextInfo 上。盘中逐 K 可能回滚。日期戳放模块级变量或普通对象。

QMT:日期戳 + done

python
#coding:gbk
from datetime import datetime

_last_job_date = ''

def init(C):
    C.done = False

def handlebar(C):
    if not C.is_last_bar():
        return
    try:
        tag = C.get_bar_timetag(C.barpos)
        d = datetime.fromtimestamp(tag / 1000).strftime('%Y%m%d')
    except Exception:
        d = datetime.now().strftime('%Y%m%d')
    global _last_job_date
    if _last_job_date == d:
        return
    print('today once', d)
    # 这里打一次接口 / 写一次日志
    _last_job_date = d

只要「进程里只跑一次」(回测整个区间一次),用 C.done

python
def init(C):
    C.done = False

def handlebar(C):
    if C.done or not C.is_last_bar():
        return
    print('whole run once')
    C.done = True

实盘跨日要把 done 按日期清掉,否则第二天不再进。

PTrade:按 context.current_dt

python
def initialize(context):
    g.last_job_date = None

def handle_data(context, data):
    d = context.current_dt.strftime('%Y%m%d')
    if g.last_job_date == d:
        return
    log.info('today once %s', d)
    g.last_job_date = d

run_daily 一天本来一次,仍建议打日期日志,方便和 handle_data 对账。

  1. 只判断 is_last_bar(),实盘同一分钟仍可能进两次。日期戳和分钟戳叠一层。
  2. 把计数器写在 C.xxx 上,定时器和 handlebar 不一定是同一个 C,对不上。用模块级变量。
  3. 日志不要每根 K 线 print 整张表,先戳再打。QMT 日志在安装目录 userdata/log
  4. 写本地 json 做持久化时,路径要在客户端能写的目录,重启后先读再跑。

相关:API 查询 · 热门问题 · 关注 / 知识星球

完整讨论和附件在 知识星球 Kimi量化研究所