liyisheng11 2024-01-28 21:29 采纳率: 100%
浏览 9
已结题

关于#python#和聚宽API的问题,请求大家解答

在聚宽平台编写回测交易代码时,发现日志中不断报错“证券代码错误:……”,但是无论如何调试,都无法找出错误,初步判断是在获取股票数据时出现了错误,但是具体原因和解决方法就不得而知了,还请大家帮忙寻找错误并加以修正,谢谢!

原代码(含对股票数据获取的调试内容但可能是调试代码有误):

from jqdata import *
import datetime
import pandas as pd

# 全局变量
g = {
    'stock_weights': {},  # 存储股票权重
    'start_date': datetime.date(2023, 4, 5),  # 设定开始日期
}

# 获取指定日期后上市的次新股
def get_subnew_stocks(start_date):
    if not isinstance(start_date, datetime.date):
        raise ValueError('start_date must be a datetime.date object')
    
    # 获取所有股票信息
    stocks = get_all_securities(types=['stock'])
    # 过滤出指定日期及以后上市的股票
    subnew_stocks = stocks[stocks['start_date'] >= start_date]
    
    # 返回次新股的股票代码列表
    return subnew_stocks.index.tolist()

# 初始化函数,设置基准和调度
def initialize(context):
    set_benchmark('000300.XSHG')  # 设置基准为沪深300指数
    set_option('use_real_price', True)  # 开启动态复权模式
    run_daily(compute_index, time='before_open')  # 开盘前运行compute_index函数

# 开盘前运行的函数
def before_trading_start(context):
    pass  # 可以在这里添加开盘前需要执行的代码

# 每天开盘前运行的函数,计算次新股权重并存储结果
def compute_index(context):
    # 获取次新股股票列表
    subnew_stocks = get_subnew_stocks(g['start_date'])
    
    # 如果次新股列表为空,则打印信息并返回
    if not subnew_stocks:
        print("没有找到符合条件的次新股")
        return
    
    # 构建查询条件,获取股票的流通市值、换手率
    q = query(valuation.code, valuation.market_cap, valuation.turnover_ratio).filter(valuation.code.in_(subnew_stocks))
    # 使用当前回测或实盘日期获取基本面数据
    current_date = context.current_dt.date()
    df = get_fundamentals(q, date=current_date)
    
    # 如果基本面数据为空,则打印信息并返回
    if df.empty:
        print("基本面查询结果为空")
        return
    
    # 获取每只股票的当日收盘价和涨跌幅
    valid_stocks = {}  # 用于存储有效的股票数据
    total_pct_change = 0.0  # 用于计算涨跌幅总和
    for stock in subnew_stocks:
        try:
            daily_data = get_price(stock, end_date=current_date, frequency='daily', fields=['close', 'pre_close'])
            
            # 调试:检查数据的格式和内容
            if not isinstance(daily_data, pd.DataFrame):
                print(f"股票 {stock} 的数据不是pandas DataFrame格式")
                continue
            if 'close' not in daily_data.columns or 'pre_close' not in daily_data.columns:
                print(f"股票 {stock} 的数据中没有包含'close'或'pre_close'字段")
                continue
            if daily_data['close'].empty or daily_data['pre_close'].empty:
                print(f"股票 {stock} 的收盘价或前收盘价数据为空")
                continue
            
            close_price = daily_data['close'][0]
            pre_close_price = daily_data['pre_close'][0]
            
            # 调试:检查价格是否为数字
            if not (isinstance(close_price, (int, float)) and isinstance(pre_close_price, (int, float))):
                print(f"股票 {stock} 的收盘价或前收盘价不是数字")
                continue
            
            pct_change = (close_price - pre_close_price) / pre_close_price
            valid_stocks[stock] = pct_change
            total_pct_change += pct_change
        except Exception as e:
            print(f"Error getting price data for stock {stock}: {e}")
            continue
    
    if not valid_stocks:
        print("没有获取到有效的股票价格数据")
        return
    
    for stock, pct_change in valid_stocks.items():
        g['stock_weights'][stock] = pct_change / total_pct_change

# 交易时运行的函数
def handle_data(context, data):
    total_value = context.portfolio.total_value
    for stock, weight in g['stock_weights'].items():
        value_per_stock = total_value * weight
        if stock not in data:
            print(f"证券代码错误: {stock}")
            continue
        order_target_value(stock, value_per_stock)


日志报错:
2023-04-07 09:30:00 - INFO - 证券代码错误: 001239.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001282.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001286.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001287.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001306.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001324.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001326.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001328.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001358.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001360.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001367.XSHE

2023-04-07 09:30:00 - INFO - 证券代码错误: 001373.XSHE

img


上图为日志报错内容

  • 写回答

14条回答 默认 最新

  • 檀越@新空间 2024-01-28 21:52
    关注

    参考ChatGPT

    从日志中看到报错信息 "证券代码错误",主要是在交易时运行的函数 handle_data 中发生的。在报错的信息中,每个错误都显示了具体的证券代码(如 "001239.XSHE")。

    在代码中,首先通过 get_subnew_stocks 函数获取了次新股的股票列表 subnew_stocks,然后在 compute_index 函数中获取了这些股票的基本面数据和价格数据。最后,在 handle_data 函数中根据计算的权重执行了交易。

    出现证券代码错误的原因可能是在 compute_index 函数中获取股票价格数据时出现问题。在你的代码中,你使用了 get_price 函数来获取股票价格数据,但在处理过程中可能发生了异常,导致无法正确获取价格数据,从而导致在 handle_data 函数中出现了证券代码错误。

    为了解决问题,你可以在 compute_index 函数中增加一些调试信息,以便更好地理解发生错误的原因。在 try 语句块中,你可以输出一些额外的信息,比如打印股票代码、当前日期等。这将帮助你更好地定位问题所在。

    修改后的 compute_index 函数:

    def compute_index(context):
        # 获取次新股股票列表
        subnew_stocks = get_subnew_stocks(g['start_date'])
        
        # 如果次新股列表为空,则打印信息并返回
        if not subnew_stocks:
            print("没有找到符合条件的次新股")
            return
        
        # 构建查询条件,获取股票的流通市值、换手率
        q = query(valuation.code, valuation.market_cap, valuation.turnover_ratio).filter(valuation.code.in_(subnew_stocks))
        # 使用当前回测或实盘日期获取基本面数据
        current_date = context.current_dt.date()
        df = get_fundamentals(q, date=current_date)
        
        # 如果基本面数据为空,则打印信息并返回
        if df.empty:
            print("基本面查询结果为空")
            return
        
        # 获取每只股票的当日收盘价和涨跌幅
        valid_stocks = {}  # 用于存储有效的股票数据
        total_pct_change = 0.0  # 用于计算涨跌幅总和
        for stock in subnew_stocks:
            try:
                daily_data = get_price(stock, end_date=current_date, frequency='daily', fields=['close', 'pre_close'])
                
                # 调试:检查数据的格式和内容
                if not isinstance(daily_data, pd.DataFrame):
                    print(f"股票 {stock} 的数据不是pandas DataFrame格式")
                    continue
                if 'close' not in daily_data.columns or 'pre_close' not in daily_data.columns:
                    print(f"股票 {stock} 的数据中没有包含'close'或'pre_close'字段")
                    continue
                if daily_data['close'].empty or daily_data['pre_close'].empty:
                    print(f"股票 {stock} 的收盘价或前收盘价数据为空")
                    continue
                
                close_price = daily_data['close'][0]
                pre_close_price = daily_data['pre_close'][0]
                
                # 调试:检查价格是否为数字
                if not (isinstance(close_price, (int, float)) and isinstance(pre_close_price, (int, float))):
                    print(f"股票 {stock} 的收盘价或前收盘价不是数字")
                    continue
                
                pct_change = (close_price - pre_close_price) / pre_close_price
                valid_stocks[stock] = pct_change
                total_pct_change += pct_change
            except Exception as e:
                print(f"Error getting price data for stock {stock} on {current_date}: {e}")
                continue
        
        if not valid_stocks:
            print("没有获取到有效的股票价格数据")
            return
        
        for stock, pct_change in valid_stocks.items():
            g['stock_weights'][stock] = pct_change / total_pct_change
    

    通过增加调试信息,你可以更容易地找到问题所在。一旦找到问题,你可以进一步修改代码以解决它。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(13条)

报告相同问题?

问题事件

  • 系统已结题 2月8日
  • 已采纳回答 1月31日
  • 创建了问题 1月28日