如何提升Yahoo finance(yf)获取ticker.info字段的响应速度
多余请求的产生原因
1. yfinance库本身的设计问题
你调用的Ticker.info属性在旧版本yfinance中默认会拉取标的全量数据,除了基础行情外,还会自动请求股东列表、财务数据、持仓信息等你不需要的接口,对应你看到的额外3次GET请求,这些多余请求直接拖慢了响应速度。
2. 业务代码重复触发请求
你观察到的两轮重复请求,大概率是两处逻辑重复调用了lookup1:一是你路由的循环中已经查询了一次股票信息,二是index.html模板渲染时又重复调用lookup1获取价格或名称字段,相当于每个标的查了两次。
另外你把单条response.info转DataFrame的操作完全多余,没有必要为了3个字段引入DataFrame的序列化开销。
高效优化方案
1. 替换为轻量化的行情接口
用yfinance专门优化过的fast_info属性替代info,fast_info只会拉取基础行情字段,不会触发多余的财务、股东接口请求,速度比info快3倍以上,优化后的lookup1可以直接返回字典,不需要转DataFrame:
def lookup1(symbol): ticker = yf.Ticker(symbol) fast_info = ticker.fast_info return { "shortName": fast_info.get("shortName", symbol), "currentPrice": fast_info.get("lastPrice", 0), "symbol": symbol }
2. 批量查询替代单标的循环请求
你当前循环中每个标的单独发请求,改成一次性批量查询所有需要的标的,仅触发1次请求即可拿到所有数据:
@app.route("/") @login_required def index(): """Show portfolio of stocks""" stocks = db.execute("SELECT symbol, SUM(number_of_shares) as sumshares, AVG(price) as avgprice FROM 'transaction' WHERE user_id = :i_d GROUP BY symbol", i_d=session["user_id"]) cash = db.execute("SELECT cash FROM users WHERE id = ?", session["user_id"])[0]["cash"] totalPortValue = 0 # 先收集所有需要查询的标的,过滤掉持仓为0的标的 valid_symbols = [stock["symbol"] for stock in stocks if stock["sumshares"] > 0] batch_quotes = {} if valid_symbols: # 批量拉取最新行情,开启多线程提升速度 batch_data = yf.download(tickers=valid_symbols, period='1d', interval='1m', group_by='ticker', threads=True) for symbol in valid_symbols: batch_quotes[symbol] = { "currentPrice": batch_data[symbol]['Close'].iloc[-1], # 股票名称建议存在本地库,这里可以直接取缓存 "shortName": symbol # 替换为你本地存储的名称即可 } for stock in stocks: sumshares = stock['sumshares'] symbol = stock['symbol'] if sumshares == 0: stock['ap'] = 0 db.execute("DELETE FROM 'transaction' WHERE symbol = :symbol AND user_id =:ui", symbol=symbol, ui=session["user_id"]) continue # 直接从批量查询结果取数,不用单独发请求 quote = batch_quotes.get(symbol, {"currentPrice": 0, "shortName": symbol}) price = float(quote["currentPrice"]) stock['name'] = quote["shortName"] stock['ap'] = price stock['total'] = sumshares * price totalPortValue += sumshares * price availableCash = cash grandTotal = availableCash + totalPortValue return render_template("/index.html",availableCash=availableCash, stocks=stocks, totalPortValue=totalPortValue, grandTotal=grandTotal)
3. 增加缓存避免重复查询
- 静态字段如股票名称
shortName不会变动,可以新增一张stock_info表存在本地数据库,第一次查询后就存入,后续不需要再请求接口。 - 价格字段可以用
flask-caching加内存缓存,设置30-60秒的有效期,短时间内用户刷新页面不会重复请求接口。
4. 排查模板重复调用
检查index.html模板,确认没有在循环中再次调用lookup1获取价格或名称,直接使用路由中已经赋值好的stock['name']、stock['ap']等字段即可。
内容的提问来源于stack exchange,提问作者Oris
相关产品推荐
相关产品推荐

