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

基于OpenRouter免费模型的日内金融分析脚本技术咨询

日内金融分析自动化方案优化答疑

问题背景

我用OpenRouter免费模型实现日内金融分析自动化,Python脚本会轮询多个LLM端点,传入股票代码、涨跌幅及收盘价生成分析内容。若某模型出现API错误、空响应等故障,自动尝试下一个模型;所有模型失败则启用规则分析降级。已将OpenRouter API密钥配置到环境变量,但不确定当前错误处理与轮询机制是否健壮;同时想了解传递自定义请求头、金融数据提示词格式化的最佳实践,以及当前轮询策略与降级方案是否适合生成简洁规范的日内金融摘要。

参考代码

import os
import requests
import json

# ================================================================
# ENV-BASED API KEY (YOU MUST SET IN TERMINAL or ~/.zshrc)
# ================================================================

OPENROUTER_API_KEY = os.getenv("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", "")

OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"

# ==========================
# MULTI-MODEL ROTATION LIST
# ==========================

FREE_MODELS = [
    "x-ai/grok-4.1-fast:free",
    "z-ai/glm-4.5-air:free",
    "deepseek/deepseek-chat-v3-0324:free",
    "deepseek/deepseek-r1-0528:free",
    "qwen/qwen3-coder:free",
    "nvidia/nemotron-nano-12b-v2-vl:free",
    "google/gemma-3-27b-it:free",
]


# ================================================================
# RULE-BASED FALLBACK
# ================================================================

def fallback_insight(symbol, change, close_price):
    direction = "up" if change > 0 else "down" if change < 0 else "flat"
    return (
        f"[Fallback] {symbol}: price is {direction} ({change:+.2f}) at {close_price:.2f}. "
        f"LLM unavailable, using rule-based analysis."
    )


# ================================================================
# MAIN FUNCTION (called from Pathway)
# ================================================================

def generate_market_insight(symbol, change, close_price):
    print("\n=====================================================")
    print(f"[DEBUG] LLM call triggered for {symbol}")
    print("=====================================================\n")

    if not OPENROUTER_API_KEY or not OPENROUTER_API_KEY.startswith("sk-or-"):
        print("[ERROR] Missing or invalid OPENROUTER_API_KEY")
        return fallback_insight(symbol, change, close_price)

    prompt = f"""
You are a professional financial market analyst.
Write a short intraday analysis in clean, concise English.

Instrument:
- Symbol: {symbol}
- Change: {change:+.2f}
- Last Close: {close_price:.2f}

Rules:
- Trend should be based on magnitude and direction of move.
- Mention risk (low/medium/high).
- Explain if the move is normal intraday noise or meaningful.
- Write 5–7 bullet points.
- Must be unique for this specific stock. No generic filler.
"""

    # Try each model one by one
    for model in FREE_MODELS:
        print(f"\n[DEBUG] Trying model: {model}")

        body = {
            "model": model,
            "messages": [
                {"role": "user", "content": prompt.strip()}
            ],
            "max_tokens": 220,
            "temperature": 0.9,
            "top_p": 0.9,
        }

        headers = {
            "Authorization": f"Bearer {OPENROUTER_API_KEY}",
            "Content-Type": "application/json",
            "HTTP-Referer": "http://localhost",
            "X-Title": "GGSIPU-Financial-Monitoring",
        }

        try:
            print("[DEBUG] Sending request to OpenRouter...")
            resp = requests.post(OPENROUTER_URL, json=body, headers=headers, timeout=40)
            print(f"[DEBUG] HTTP Status = {resp.status_code}")

            if resp.status_code != 200:
                print("[ERROR] Model failed:", model, resp.text[:180])
                continue

            data = resp.json()

            if "error" in data:
                print("[ERROR] API Model Error:", data["error"])
                continue

            content = data["choices"][0]["message"]["content"]
            if not content:
                print("[ERROR] Model returned empty content.")
                continue

            print(f"[DEBUG] SUCCESS with model: {model}")
            return content.strip()

        except Exception as e:
            print(f"[EXCEPTION] Model crashed: {model} → {repr(e)}")
            continue

    print("[ERROR] ALL MODELS FAILED → fallback triggered.")
    return fallback_insight(symbol, change, close_price)

针对性解答

一、错误处理与轮询机制健壮性优化

现有逻辑基础可行,但存在可优化点:

  • 补充分类错误处理:解析API返回的error字段,针对rate_limit_exceeded、quota_exceeded这类免费模型高频错误,标记该模型短时间内不可用,避免无效重试;
  • 差异化超时设置:免费模型响应速度差异大,可将超时时间调整为15-30秒区间,而非固定40秒;
  • 增加单模型重试:对单个模型最多重试1次(应对临时网络波动),但需注意免费模型的配额限制,避免触发更严格的限流;
  • 细分异常捕获:将通用Exception拆分为requests.exceptions.ConnectionError、requests.exceptions.Timeout等具体类型,日志更精准,便于排查问题。

二、自定义请求头最佳实践

OpenRouter对自定义头有明确要求,需注意:

  • 必填头规范:HTTP-Referer需填写真实的应用域名或本地开发地址(如http://localhost:8000),不能留空或填虚假地址;X-Title填写清晰的应用名称,帮助平台识别请求来源;
  • 可选头增强:添加X-OpenRouter-Source头标记应用类型(如financial-analytics-bot),提升请求合规性;
  • 安全注意:敏感信息仅通过Authorization头的Bearer令牌传递,不要在其他自定义头中包含密钥或用户数据。

三、金融数据提示词格式化最佳实践

现有提示词结构清晰,可进一步优化输出质量:

  • 结构化数据传递:用JSON格式封装金融数据,让LLM更易解析,示例:
    Instrument Data:
    {
      "symbol": "{symbol}",
      "change_pct": "{change:+.2f}%",
      "close_price": "{close_price:.2f}"
    }
    
  • 明确输出格式:在规则中指定每个 bullet 点的固定结构,比如"- 趋势判断:[方向+幅度],属于[正常波动/显著异动],风险等级[低/中/高]:[简短理由]",避免输出混乱;
  • 约束上下文:明确提示"基于日内涨跌幅数据,仅分析当日走势,不涉及长期趋势预测",避免LLM生成无关内容;
  • 控制语气:要求输出"专业、客观、简洁",避免情绪化表述。

四、轮询策略与降级方案适配性

当前方案适配基础需求,可进一步优化:

  • 轮询策略优化:
    • 基于历史成功率排序:记录每个模型的成功/失败次数,优先调用成功率高的模型,提升整体效率;
    • 随机轮询:避免多个请求集中调用热门免费模型,降低触发限流的概率;
  • 降级方案增强:
    • 根据涨跌幅幅度划分等级(如±1%以内为正常波动,±3%以上为显著异动),对应不同的风险等级描述;
    • 若能获取成交量数据,添加成交量维度判断异动是否有支撑,让规则分析更有价值;
    • 保持输出格式与LLM一致(如同样用5-7个bullet点),减少下游处理的适配成本。

内容的提问来源于stack exchange,提问作者Ad Du

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 00:05:55