问题描述
#coding:gbk
import time
# 单独维护交易日期
trade_date = "2024-12-27"
# 固定的交易时间
sell_time = "10:05:01"
buy_time = "10:05:05"
# 假设这些是您要卖出和买入的股票代码和金额
sell_stocks_info = [
{'stock_code': '161631.sz', 'amount': 200},
# {'stock_code': '000002.SZ', 'amount': 15000}
]
buy_stocks_info = [
{'stock_code': '161631.SZ', 'amount': 200},
# {'stock_code': '000004.SZ', 'amount': 8000}
]
def init(ContextInfo):
print("程序开始运行了天爷...")
# 设置定时器,在指定日期和卖出时间触发卖出操作
ContextInfo.run_time("sell_stocks", "1nSecond", trade_date + " " + sell_time)
# 设置定时器,在指定日期和买入时间触发买入操作
ContextInfo.run_time("buy_stocks", "1nSecond", trade_date + " " + buy_time)
def sell_stocks(ContextInfo):
# 卖出股票的代码逻辑
for stock in sell_stocks_info:
passorder(24, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
def buy_stocks(ContextInfo):
# 买入股票的代码逻辑
for stock in buy_stocks_info:
passorder(23, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
def handlebar(ContextInfo):
return
解决方案
导致您的代码一直循环买入卖出的原因在于 ContextInfo.run_time 函数的第二个参数设置。
在您的代码中:
ContextInfo.run_time("sell_stocks", "1nSecond", trade_date + " " + sell_time)
这里的 "1nSecond" 表示每隔1秒钟重复调用一次回调函数。因此,当时间到达您设定的 startTime 后,系统就会每秒钟执行一次 sell_stocks 和 buy_stocks,从而导致无限循环下单。
解决方法
如果您只希望在指定时间执行一次,可以通过设置全局标志位(Flag)来控制,或者改用在 handlebar 中判断时间的方式。
方案一:使用全局标志位控制(推荐修改最少)
在 ContextInfo 中添加标志位,执行过一次后就将其设为 True,下次触发时直接跳过。
#coding:gbk
import time
trade_date = "2024-12-27"
sell_time = "10:05:01"
buy_time = "10:05:05"
sell_stocks_info = [{'stock_code': '161631.SZ', 'amount': 200}]
buy_stocks_info = [{'stock_code': '161631.SZ', 'amount': 200}]
def init(ContextInfo):
print("程序开始运行了...")
# 初始化标志位,防止重复下单
ContextInfo.has_sold = False
ContextInfo.has_bought = False
# 依然使用定时器,但内部会判断标志位
ContextInfo.run_time("sell_stocks", "1nSecond", trade_date + " " + sell_time)
ContextInfo.run_time("buy_stocks", "1nSecond", trade_date + " " + buy_time)
def sell_stocks(ContextInfo):
if not ContextInfo.has_sold:
print("执行卖出操作")
for stock in sell_stocks_info:
passorder(24, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
ContextInfo.has_sold = True # 标记为已卖出
def buy_stocks(ContextInfo):
if not ContextInfo.has_bought:
print("执行买入操作")
for stock in buy_stocks_info:
passorder(23, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
ContextInfo.has_bought = True # 标记为已买入
def handlebar(ContextInfo):
pass
方案二:在 handlebar 中判断时间(更符合行情驱动逻辑)
不使用 run_time,而是利用 QMT 的行情驱动机制,在 handlebar 中获取当前时间进行判断。
#coding:gbk
import time
trade_date = "20241227" # 注意时间格式转换为纯数字方便比较
sell_time = "100501"
buy_time = "100505"
sell_stocks_info = [{'stock_code': '161631.SZ', 'amount': 200}]
buy_stocks_info = [{'stock_code': '161631.SZ', 'amount': 200}]
def init(ContextInfo):
print("程序开始运行了...")
ContextInfo.has_sold = False
ContextInfo.has_bought = False
def handlebar(ContextInfo):
# 获取当前K线/Tick的时间戳并转换为字符串
tick_time = ContextInfo.get_tick_timetag()
current_date = time.strftime("%Y%m%d", time.localtime(tick_time / 1000))
current_time = time.strftime("%H%M%S", time.localtime(tick_time / 1000))
# 判断日期是否匹配
if current_date == trade_date:
# 判断卖出时间
if current_time >= sell_time and not ContextInfo.has_sold:
print("到达卖出时间,执行卖出")
for stock in sell_stocks_info:
passorder(24, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
ContextInfo.has_sold = True
# 判断买入时间
if current_time >= buy_time and not ContextInfo.has_bought:
print("到达买入时间,执行买入")
for stock in buy_stocks_info:
passorder(23, 1102, '8886006288', stock['stock_code'], 5, -1, stock['amount'], ContextInfo)
ContextInfo.has_bought = True
总结:run_time 是一个循环定时器,如果只需要单次触发,必须配合状态变量(如 True/False)来拦截后续的重复执行。