You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spyder定时获取NSE期权链数据异常:重试循环与数据空白排查

NSE期权链定时获取数据异常排查与修复

我用Spyder IDE写Python代码抓取印度国家证券交易所(NSE)的期权链数据:

  • 不设置定时器时,代码能正常把数据写入Excel,Variable Explorer里也能看到对应的DataFrame
  • 加上1分钟定时获取逻辑后,Excel文件和Variable Explorer全空白;有时候能按1分钟间隔正常获取,有时候会陷入无限"Retrying"循环,搞不懂Variable Explorer空白的原因。

可正常运行的代码(无定时逻辑)

import requests
import json
import pandas as pd
import xlwings as xw
import time
from datetime import datetime
import winsound

file = xw.Book("NiftyOptionChainFeed.xlsm")
sh1 = file.sheets("Sheet1")

def oc(sym):

    url = "https://www.nseindia.com/api/option-chain-indices?symbol="+sym
    
    headers = {"Accept-Encoding": "gzip, deflate, br",
                "Accept-Language": "en-US,en;q=0.9",
                "referer": "https://www.nseindia.com/option-chain",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",}
    
    response = requests.get(url, headers = headers).text
    
    data = json.loads(response)
        
    expiry_list = data['records']['expiryDates']
    
    ce = {}
    pe = {}
    n = 0
    m = 0
    
    for i in data['records']['data']:
        #if i['expiryDate'] == expiry_date:
        try:
            ce[n] = i['CE']
            n = n + 1
        except:
            pass
        try:
            pe[m] = i['PE']
            m = m + 1
        except:
            pass
    
    ce_df = pd.DataFrame.from_dict(ce).transpose()
    ce_df.columns = "CE_" + ce_df.columns
    pe_df = pd.DataFrame.from_dict(pe).transpose()
    pe_df.columns = "PE_" + pe_df.columns
        
    df = pd.concat([ce_df, pe_df],axis = 1)
    
    return expiry_list, df

try:
    data = oc(sym)
    sh1.range("A1").value = data[1]
    sh1.range("AO2").options(transpose = True).value = data[0]
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    sh1.range("AQ2").value = timestamp
    time.sleep(90)
except:
    print("retrying")
    time.sleep(5)

出现异常的代码(含定时相关逻辑)

import requests
import json
import pandas as pd
import xlwings as xw
import time
from datetime import datetime
import winsound

def oc(sym):

    url = "https://www.nseindia.com/api/option-chain-indices?symbol="+sym
    
    headers = {"Accept-Encoding": "gzip, deflate, br",
                "Accept-Language": "en-US,en;q=0.9",
                "referer": "https://www.nseindia.com/option-chain",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",}
    
    response = requests.get(url, headers = headers).text
    
    data = json.loads(response)
        
    expiry_list = data['records']['expiryDates']
    
    ce = {}
    pe = {}
    n = 0
    m = 0
    
    for i in data['records']['data']:
        #if i['expiryDate'] == expiry_date:
        try:
            ce[n] = i['CE']
            n = n + 1
        except:
            pass
        try:
            pe[m] = i['PE']
            m = m + 1
        except:
            pass
    
    ce_df = pd.DataFrame.from_dict(ce).transpose()
    ce_df.columns = "CE_" + ce_df.columns
    pe_df = pd.DataFrame.from_dict(pe).transpose()
    pe_df.columns = "PE_" + pe_df.columns
        
    df = pd.concat([ce_df, pe_df],axis = 1)
    
    file = xw.Book("NiftyOptionChainFeed.xlsm")
    sh1 = file.sheets("Sheet1")
    sh1.range("A1").value = df
    sh1.range("AO2").options(transpose = True).value = expiry_list

问题根源分析

  1. Excel对象重复绑定:异常代码里每次调用oc()都会重新打开Excel文件,多次实例化会导致xlwings的对象引用混乱,数据无法正常写入。
  2. 变量作用域局限:df、expiry_list都是函数内部的局部变量,函数执行完就被销毁,Spyder的Variable Explorer只能追踪全局变量,所以显示空白。
  3. 无异常处理机制:定时场景下网络波动更频繁,但异常代码没有错误捕获,请求失败后直接中断流程,没有重试逻辑,要么空白要么无限卡死。
  4. 定时逻辑缺失:提供的异常代码里没有完整的定时循环(比如while True),如果是手动添加的逻辑位置错误,会导致执行流程异常。

修复后的完整代码

import requests
import json
import pandas as pd
import xlwings as xw
import time
from datetime import datetime

# 全局初始化Excel,避免重复打开
file = xw.Book("NiftyOptionChainFeed.xlsm")
sh1 = file.sheets("Sheet1")

def oc(sym):
    url = f"https://www.nseindia.com/api/option-chain-indices?symbol={sym}"
    
    headers = {
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-US,en;q=0.9",
        "referer": "https://www.nseindia.com/option-chain",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
    
    try:
        # 添加超时,避免无限等待
        response = requests.get(url, headers=headers, timeout=10)
        # 触发HTTP错误(比如403、500)
        response.raise_for_status()
        data = json.loads(response.text)
    except Exception as e:
        print(f"请求出错: {str(e)}")
        return None, None
        
    expiry_list = data['records']['expiryDates']
    
    ce = {}
    pe = {}
    n = 0
    m = 0
    
    for i in data['records']['data']:
        # 只捕获KeyError,避免掩盖其他严重错误
        try:
            ce[n] = i['CE']
            n += 1
        except KeyError:
            pass
        try:
            pe[m] = i['PE']
            m += 1
        except KeyError:
            pass
    
    ce_df = pd.DataFrame.from_dict(ce).transpose()
    ce_df.columns = "CE_" + ce_df.columns
    pe_df = pd.DataFrame.from_dict(pe).transpose()
    pe_df.columns = "PE_" + pe_df.columns
        
    df = pd.concat([ce_df, pe_df], axis=1)
    
    return expiry_list, df

# 定时执行主逻辑
if __name__ == "__main__":
    sym = "NIFTY"  # 替换为你需要的标的
    while True:
        expiry_list, df = oc(sym)
        if df is not None and not df.empty:
            # 写入Excel
            sh1.range("A1").value = df
            sh1.range("AO2").options(transpose=True).value = expiry_list
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            sh1.range("AQ2").value = timestamp
            print(f"数据更新成功: {timestamp}")
        else:
            print("获取数据失败,即将重试")
        
        # 间隔1分钟执行一次
        time.sleep(60)

关键修复点

  • 全局Excel实例:把Excel文件打开放在函数外,避免重复加载导致的资源冲突。
  • 变量作用域优化:函数返回数据到全局循环中,Spyder的Variable Explorer能追踪到expiry_list和df变量。
  • 完善异常处理:添加网络请求超时、HTTP错误捕获,明确失败原因,避免静默失败。
  • 规范定时循环:用while True+time.sleep(60)实现稳定的定时任务,确保每次流程完整。
  • 精准异常捕获:替换宽泛的except:为具体的KeyError,避免掩盖其他严重问题。

内容的提问来源于stack exchange,提问作者Mohammad Haneef Ahmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:07:19