金字塔决策交易系统

 找回密码
 

微信登录

微信扫一扫,快速登录

搜索
12
返回列表 发新帖
楼主: hanzi-999

为何实盘行情我用history_bars_date函数无法获取到5分钟级别和30分钟级别的K线

[复制链接]

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-6-27 14:48 | 显示全部楼层
如截图

补充内容 (2025-6-27 14:54):
*软件设置里,K线周期划分规则是按交易时间划分的;
*上午断过网,但我重新补了近几天的5分钟数据
截图202506271445369106.png
截图202506271447165558.png
截图202506271448394570.png
回复

使用道具 举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2025-6-27 16:36 | 显示全部楼层
你这个报错没看出来问题呀。看上去似乎不是我们接口调用的问题吧。
金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-6-27 22:56 | 显示全部楼层
你看我一楼发的, 因为30分钟K不对,所以断言失败哦

补充内容 (2025-6-27 22:58):
说错了.是 2025-6-27 14:00发的内容,30分钟K不对,所以断言失败
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-6-30 17:17 | 显示全部楼层
这个还请尽快验证以及修复啊
回复

使用道具 举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2025-7-1 08:41 | 显示全部楼层
你这个报错是你自己代码里的。我们需要的是原始接口报错,你给这种报错信息给我们 我们不可能还把你代码理一遍的。
最简单方式就你把数据打印出来,看看到底获取了什么,而不是间接的通过你的代码逻辑去定位问题。
金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-7-1 09:19 | 显示全部楼层
1.不是让你们帮我理代码
2.我提供这个日志是向你们表明我确实遇到这个接口bug,且我比较确定这是接口返回数据不对导致的(层次关系我也已通过截图让你们知晓); 而且之前也反应过history_bars_date及history_bars函数的问题
3.因为规范的开发和发布应该都是须经过详细的测试,所以,我原以为你们的开发部门会有详细的测试用例(即使不完善也可以补充), 不需要我再提供我具体的抽离出来的代码, 毕竟我的日志是镶嵌在具体的策略中,而策略代码较复杂,我虽然可以写抽离出的测试代码, 但毕竟较花时间
4.具体什么情况下出现的,对应的合约及查询的参数我都在帖子标题和一楼做了说明

补充内容 (2025-7-1 09:26):
第4点说错了, 是10楼 发表于 2025-6-27 14:00 的帖子里做了具体的说明;  因为是和本帖子密切相关的,所以我就没有另开帖子而是在10楼开始追加反应的
回复

使用道具 举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2025-7-1 09:56 | 显示全部楼层
“我提供这个日志是向你们表明我确实遇到这个接口bug,且我比较确定这是接口返回数据不对导致的
你这个报错如果能稳定重新,你就额外打印下数据  直接看下输出的K数据就行了。其他的内容 帮助不了我们定位问题的呀。 首先要看到明确现象,而不是你自身代码报错。你这个报错相当于告诉我们 出错了。但是怎么错的,错在哪里 都一无所知的呀。
金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-7-1 10:10 | 显示全部楼层
你可能没看全我在10楼的意思,PG00在2025-06-27  13:40时的30分钟级别K,最新的K应该是时标13:45:00(因为我传给history_bars_date的end_date参数就是2025-06-27 13:45:00), 但是打印表明接口得到的最新一根K是2025-06-27 11:45:00
补充:我软件的K线周期划分是'交易时间划分'


补充内容 (2025-7-1 10:13):
当时是仿真盘时出现的,也就是当时是现实时间
截图202507011001585085.png
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-7-3 11:27 | 显示全部楼层
hello,
我写了专门的测试代码,回测再现了这个错误,30m级别时标对不上.
具体信息如附图
补充说明:5分钟级别数据全市场之前做过下载补充从2015年到2025年;回测级别及基准如截图

补充内容 (2025-7-3 11:29):
正确的30分钟最新K应该是10:45:00,但是查询返回的K却是10:30:00

补充内容 (2025-7-3 11:40):
基准品种:AG00, 基准级别5m
截图202507031124319638.png
回复

使用道具 举报

45

主题

259

帖子

259

积分

等级: 免费版

注册:
2023-9-29
曾用名:
 楼主| 发表于 2025-7-3 11:38 | 显示全部楼层
我的测试代码根据时间节点传递给 history_bars_date函数的start_date, end_date参数.
我的时间节点信息获取在自有jzt_fuLegalStamp包中,另外交易日历类TradeCalendar是在自有包jzt_trade_calendar中.
由于这些包的代码较长, 如果你们有自己的时间节点信息获取函数,你们可自行替代. 如需要我提供,也可.
如下是我的测试代码:
##############################################################################
#                      test_history_bars_date
##############################################################################
import time
import datetime as DateTime
from jzt_trade_calendar import *   
from jzt_fuLegalStamp import *  
from PythonApi import *
   
class GlobalCls:
    def _init_(self):
        self.name = 'global var'
g = GlobalCls()
  
def IsPaperTrading(context):
    return context.run_info.run_type == 'paper_trading'   
#----------------------------------------
def init(context):
    g.context = context
    Print(f"context.run_info.frequency:{context.run_info.frequency}")
    Print(f"context.run_info.base_book_id:{context.run_info.base_book_id}")
    #-------------------------------------------------------------
    #                交易日历相关
    #-------------------------------------------------------------  
    earlyest_market_date = DateTime.datetime.strptime('19930915','%Y%m%d')
    if context.run_info.run_type == 'backtest':  
        start_date = context.run_info.start_date
    else:
        start_date = GetBasebookCurstamp()
    tmp_beg_dt = start_date - DateTime.timedelta(days=365*1) #PS:向前推1年
   
    if tmp_beg_dt.year < earlyest_market_date.year:
        tmp_beg_dt = earlyest_market_date
        
    tmp_end_dt = context.run_info.end_date + DateTime.timedelta(days=365*5) #PS:向后推x年
    #PS:仅返回回测或实盘时对应合约的历史交易日list,交易日类型是datetime.datetime
    context.tradedate_lst = get_trading_dates(tmp_beg_dt,tmp_end_dt) #获取交易日历
    #Print(f"get_trading_dates({tmp_beg_dt},{tmp_end_dt}) ret list. list[0]:{context.tradedate_lst[0]} list[-1]:{context.tradedate_lst[-1]}")
    #assert( context.tradedate_lst[0]-tmp_beg_dt < DateTime.timedelta(days=20) ) #获得的最早日期不能比要查询的起始日期过大
   
    g.trade_calendar = TradeCalendar(context.tradedate_lst)
      
    #-------------------------------------------------------------
    g.fu_1mtp_man = FuXmTimepointMan(1) #1分钟K时间节点管理对象
    g.fu_5mtp_man = FuXmTimepointMan(5) #5分钟K时间节点管理对象
    g.fu_30mtp_man = FuXmTimepointMan(30) #30分钟K时间节点管理对象
    #-------------------------------------------------------------
    if 0:
        context.universe = ['INSC0000',  
                    'SQHC00',   
                    'SQRU00',   
                    'SQSP00',   
                    'SQAU00',   
                    'INNR00',   
                    'DQV00',     
                    'ZQTA00',   
                    'ZQFG00',   
                    'DQM00',     
                    'DQJ00',     
                    'SQSN00',   
                    'ZQRM00',   
                    'ZQCF00',   
                    'DQEB00',   
                    'SQRB00',   
                    'SQPB00',   
                    'SQAG00',   
                    'DQPG00',   
                    'DQB00',     
                    'SQCU00',   
                    'DQJD00',   
                    'DQY00',     
                    'DQI00',     
                    'SQNI00',   
                    'DQP00',     
                    'ZQUR00',   
                    'ZQSA00',   
                    'ZQSF00',   
                    'SRX00', #'ZQSRX00',   
                    'AX00',  #'DQAX00',   
                    'ZQAP00',   
                    'ZQMA00',
                    'DQJM00'
                    ]
    else:
        context.universe = ['ZQSM00']
        
    Print("init finish")
    pass

# before_trading此函数会在每天基准合约的策略交易开始前被调用,当天只会被调用一次。--(选择实现)
def before_trading(context):
    pass


# 你选择的品种的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新。--(必须实现)
def handle_bar(context):
    #symbol = 'DQPG00'
    HISTORY_ITEMS_LIST = ['datetime', 'close']  
    STAMP_INDEX = 0
   
    target_dt = GetBasebookCurstamp()
    if target_dt != GetFuTimepoint('5m', target_dt):
        return
        
    is_all_symbols_bars_ok = True
    for symbol in context.universe:
        base_bars = history_bars(symbol, 1, context.run_info.frequency, HISTORY_ITEMS_LIST, include_now=True)
        #若该品种未休盘
        if len(base_bars) and PyramidBarStampToDatetime(base_bars[-1,STAMP_INDEX]) == target_dt:
            #获取所处30m级别K线--
            freq = '30m'  
            end_dt = GetFuTimepoint(freq, target_dt)
            pre_tp = GetFuPrexTimepoint(freq, target_dt)  
            bars_help = history_bars_date(symbol, pre_tp, end_dt, freq, HISTORY_ITEMS_LIST, include_now=True)
            
            if len(bars_help):
                fu_xmtp_man = GetFuXmtpMan(freq)  
                assert(fu_xmtp_man is not None)
                latest_bar_stamp = PyramidBarStampToDatetime(bars_help[-1,STAMP_INDEX])
                cur_timepoint = fu_xmtp_man.GetDateTimepoint_bydt(target_dt)
                if latest_bar_stamp == cur_timepoint:
                    #Print(f"{symbol} {freq} latest_bar_stamp:{latest_bar_stamp} == cur_timepoint:{cur_timepoint} ")
                    pass
                else:
                    is_all_symbols_bars_ok = False
                    Print(f"history_bars_date({symbol}, {pre_tp}, {end_dt}, {freq}, {HISTORY_ITEMS_LIST}, include_now=True) ret bars len:{len(bars_help)}")
                    info_comp = '>' if latest_bar_stamp > cur_timepoint else '<'
                    Print(f"Warning: {symbol} {freq} latest_bar_stamp:{latest_bar_stamp} {info_comp} cur_timepoint:{cur_timepoint} !")
                    assert(False)
            else:
                Print(f"Warning: history_bars_date({symbol}, {pre_tp}, {end_dt}, {freq}, {HISTORY_ITEMS_LIST}, include_now=True) ret bars len:{len(bars_help)}")
                is_all_symbols_bars_ok = False
    if is_all_symbols_bars_ok:
        #Print(f"is_all_symbols_bars_ok:{is_all_symbols_bars_ok}")
        pass
    pass
     
# after_trading函数会在每天交易结束后被调用,当天只会被调用一次。 --(选择实现)
def after_trading(context):
    pass
   
def exit(context):
    print(f"on exit")
   
def Print(content):
    dt_str = GetDatetimeForLogTag().strftime('%Y%m%d %H:%M:%S')
    print("[{}] {}".format(dt_str, content)) #PS:打印也是耗时操作   
###########################################################   
#                      时间节点相关 250620
###########################################################
def GetFuXmtpMan(freq):
    if freq == FREQ_1M: return g.fu_1mtp_man
    elif freq == FREQ_5M: return g.fu_5mtp_man
    elif freq == FREQ_30M: return g.fu_30mtp_man
    else: return None
   
def GetFuPrexTimepoint(freq:str, target_dt:DateTime.datetime):
    fu_xmtp_man = GetFuXmtpMan(freq)
    assert(fu_xmtp_man is not None)
    #if fu_xmtp_man is not None:
    return fu_xmtp_man.GetPreDateTimepoint_bydt(target_dt, g.trade_calendar)
     
def GetFuTimepoint(freq:str, target_dt:DateTime.datetime):
    fu_xmtp_man = GetFuXmtpMan(freq)
    assert(fu_xmtp_man is not None)
    #if fu_xmtp_man is not None:
    return fu_xmtp_man.GetDateTimepoint_bydt(target_dt)
   
#####################################################
#                  时间相关
#####################################################
def PyramidBarStampToDatetime(val):
    val = int(val)
    #print("PyramidBarStampToDatetime val:{}".format(val))
    return DateTime.datetime(year=int(val//10000000000),
        month= val%10000000000//100000000,
        day=   val%100000000//1000000,
        hour=  val%1000000//10000,
        minute=val%10000//100,
        second=val%100,
        microsecond=0)   
#现实时间
def GetActualDateTime():
    return DateTime.datetime.now()
     
def GetBasebookCurstamp():
    return g.context.now
   
def GetDatetimeForLogTag():
    if IsPaperTrading(g.context): return GetActualDateTime()
    else: return GetBasebookCurstamp()      

#根据程序运行模式获取当前时间(可以是模拟时间) PS:包含秒   
def GetCurrentDateTime():   
    if IsPaperTrading(g.context): return DateTime.datetime.now().replace(microsecond=0)
    else: return g.context.now.replace(microsecond=0)     
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 微信登录

本版积分规则

手机版|小黑屋|上海金之塔信息技术有限公司 ( 沪ICP备13035422号 )

GMT+8, 2025-7-3 14:08 , Processed in 0.103708 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表