#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SAGAX SDK 完整使用案例
========================
覆盖全部 11 个模块、70+ 个接口方法。

安装:
    pip install sagax-sdk

使用前请先在 SAGAX 平台申请 API Key:
    https://www.sagax.cn/api-docs
"""

from sagax import SagaxClient, AuthError, RateLimitError, NotFoundError
import json
import time

# ============================================================
# 初始化客户端
# ============================================================

client = SagaxClient(
    api_key="sagax_ak_your_api_key",       # 替换为你的 API Key
    secret_key="sagax_sk_your_secret_key", # 替换为你的 Secret Key
    base_url="https://api.sagax.cn",       # A股后端（默认）
    futures_url="https://api.sagax.cn/futures",  # 期货后端
    timeout=30,       # 默认超时 30 秒
    max_retries=3,    # 429 自动重试次数
)

def pprint(data, max_lines=8):
    """格式化打印 JSON，最多显示 max_lines 行"""
    text = json.dumps(data, ensure_ascii=False, indent=2)
    lines = text.split("\n")
    for line in lines[:max_lines]:
        print(line)
    if len(lines) > max_lines:
        print(f"  ... ({len(lines) - max_lines} more lines)")

def section(title):
    print(f"\n{'='*60}")
    print(f"  {title}")
    print(f"{'='*60}\n")


# ████████████████████████████████████████████████████████████
#                      A 股 接 口
# ████████████████████████████████████████████████████████████


# ============================================================
# 1. 市场数据 (client.market) — basic 权限
# ============================================================

section("1.1 市场概览 — market.overview()")
overview = client.market.overview()
print(f"上涨: {overview.get('up_count')}  下跌: {overview.get('down_count')}  平盘: {overview.get('flat_count')}")
print(f"总成交额: {overview.get('total_amount')}")

section("1.2 主要指数行情 — market.indices()")
indices = client.market.indices()
for idx in indices.get("data", [])[:5]:
    print(f"  {idx.get('name', '')}  {idx.get('close', '')}  {idx.get('pct_chg', '')}%")

section("1.3 板块表现 — market.sectors()")
sectors = client.market.sectors()
for s in sectors.get("data", [])[:5]:
    print(f"  {s.get('name', '')}  涨幅: {s.get('pct_chg', '')}%")

section("1.4 涨幅榜 — market.gainers(limit=5)")
gainers = client.market.gainers(limit=5)
for g in gainers.get("data", [])[:5]:
    print(f"  {g.get('ts_code', '')} {g.get('name', '')}  +{g.get('pct_chg', '')}%")

section("1.5 跌幅榜 — market.losers(limit=5)")
losers = client.market.losers(limit=5)
for g in losers.get("data", [])[:5]:
    print(f"  {g.get('ts_code', '')} {g.get('name', '')}  {g.get('pct_chg', '')}%")

section("1.6 沪深港通资金流 — market.hsgt(limit=3)")
hsgt = client.market.hsgt(limit=3)
pprint(hsgt)

section("1.7 涨跌停列表 — market.limit_list()")
limit_list = client.market.limit_list(limit_type="U", limit=5)
pprint(limit_list)

section("1.8 概念板块列表 — market.concepts()")
concepts = client.market.concepts(limit=5)
pprint(concepts)

section("1.9 概念成分股 — market.concept_stocks()")
# 先取第一个概念的 code
concept_list = concepts.get("data", [])
if concept_list:
    code = concept_list[0].get("code", "TS4")
    concept_stocks = client.market.concept_stocks(code, limit=5)
    pprint(concept_stocks)


# ============================================================
# 2. 个股数据 (client.stock) — basic / standard 权限
# ============================================================

TS_CODE = "000001.SZ"  # 平安银行

section("2.1 股票列表 — stock.list(page=1, per_page=5)")
stock_list = client.stock.list(page=1, per_page=5)
for s in stock_list.get("stocks", stock_list.get("data", []))[:5]:
    print(f"  {s.get('ts_code', '')} {s.get('name', '')}")

section("2.2 股票搜索 — stock.search('平安银行')")
results = client.stock.search("平安银行")
for r in results.get("results", results.get("data", []))[:3]:
    print(f"  {r.get('ts_code', '')} {r.get('name', '')}")

section("2.3 个股基本信息 — stock.basic()")
info = client.stock.basic(TS_CODE)
print(f"  名称: {info.get('name', '')}  行业: {info.get('industry', '')}  市场: {info.get('market', '')}")

section("2.4 日线行情 — stock.daily(days=5)")
daily = client.stock.daily(TS_CODE, days=5)
for row in daily.get("data", [])[:5]:
    print(f"  {row['trade_date']}  O:{row['open']}  H:{row['high']}  L:{row['low']}  C:{row['close']}  V:{row['vol']}")

section("2.5 K线数据(日K) — stock.kline(freq='daily', limit=5)")
kline = client.stock.kline(TS_CODE, freq="daily", limit=5)
for row in kline.get("data", [])[:5]:
    print(f"  {row['trade_date']}  O:{row['open']}  H:{row['high']}  L:{row['low']}  C:{row['close']}")

section("2.6 K线数据(周K) — stock.kline(freq='weekly', limit=3)")
kline_w = client.stock.kline(TS_CODE, freq="weekly", limit=3)
for row in kline_w.get("data", [])[:3]:
    print(f"  {row['trade_date']}  O:{row['open']}  H:{row['high']}  L:{row['low']}  C:{row['close']}")

section("2.7 最新价格 — stock.price()")
price = client.stock.price(TS_CODE)
print(f"  最新价: {price.get('close', '')}  涨跌: {price.get('change', '')}  涨幅: {price.get('pct_chg', '')}%")

section("2.8 技术指标 — stock.indicators(days=5)")
indicators = client.stock.indicators(TS_CODE, days=5)
for row in indicators.get("data", [])[:3]:
    print(f"  {row.get('trade_date', '')}  MA5:{row.get('ma5', '')}  MA20:{row.get('ma20', '')}  RSI:{row.get('rsi', '')}")

section("2.9 多因子数据 — stock.factors(days=5)")
factors_data = client.stock.factors(TS_CODE, days=5)
pprint(factors_data)

section("2.10 资金流向 — stock.moneyflow(limit=3)")
moneyflow = client.stock.moneyflow(TS_CODE, limit=3)
for row in moneyflow.get("data", [])[:3]:
    print(f"  {row.get('trade_date', '')}  净流入: {row.get('net_mf_amount', '')}")

section("2.11 融资融券 — stock.margin(limit=3)")
margin = client.stock.margin(TS_CODE, limit=3)
for row in margin.get("data", [])[:3]:
    print(f"  {row.get('trade_date', '')}  融资余额: {row.get('rzye', '')}")

section("2.12 复权因子 — stock.adj_factor(limit=3)")
adj = client.stock.adj_factor(TS_CODE, limit=3)
for row in adj.get("data", [])[:3]:
    print(f"  {row.get('trade_date', '')}  复权因子: {row.get('adj_factor', '')}")

section("2.13 涨跌停价 — stock.stk_limit(limit=3)")
stk_limit = client.stock.stk_limit(TS_CODE, limit=3)
for row in stk_limit.get("data", [])[:3]:
    print(f"  {row.get('trade_date', '')}  涨停价: {row.get('up_limit', '')}  跌停价: {row.get('down_limit', '')}")

section("2.14 大宗交易 — stock.block_trades(limit=3)")
bt = client.stock.block_trades(TS_CODE, limit=3)
pprint(bt)

section("2.15 业绩快报 — stock.express(limit=3)")
express = client.stock.express(TS_CODE, limit=3)
pprint(express)

section("2.16 限售解禁 — stock.share_float(limit=3)")
sf = client.stock.share_float(TS_CODE, limit=3)
pprint(sf)

section("2.17 股东增减持 — stock.holdertrade(limit=3)")
ht = client.stock.holdertrade(TS_CODE, limit=3)
pprint(ht)

section("2.18 利润表 — stock.income(limit=3)")
income = client.stock.income(TS_CODE, limit=3)
for row in income.get("data", [])[:2]:
    print(f"  报告期: {row.get('end_date', '')}  营收: {row.get('revenue', '')}  净利: {row.get('n_income', '')}")

section("2.19 资产负债表 — stock.balancesheet(limit=3)")
bs = client.stock.balancesheet(TS_CODE, limit=3)
for row in bs.get("data", [])[:2]:
    print(f"  报告期: {row.get('end_date', '')}  总资产: {row.get('total_assets', '')}")

section("2.20 现金流量表 — stock.cashflow(limit=3)")
cf = client.stock.cashflow(TS_CODE, limit=3)
for row in cf.get("data", [])[:2]:
    print(f"  报告期: {row.get('end_date', '')}  经营净流入: {row.get('n_cashflow_act', '')}")

section("2.21 股东人数 — stock.holdernumber(limit=3)")
hn = client.stock.holdernumber(TS_CODE, limit=3)
pprint(hn)

section("2.22 分红送股 — stock.dividend(limit=3)")
div = client.stock.dividend(TS_CODE, limit=3)
pprint(div)

section("2.23 停复牌记录 — stock.suspend(limit=3)")
suspend = client.stock.suspend(TS_CODE, limit=3)
pprint(suspend)


# ============================================================
# 3. 因子系统 (client.factors) — standard 权限
# ============================================================

section("3.1 因子列表 — factors.list()")
factor_list = client.factors.list()
for f in factor_list.get("factors", factor_list.get("data", []))[:5]:
    print(f"  {f.get('name', '')} — {f.get('display_name', f.get('description', ''))}")

section("3.2 因子分类 — factors.categories()")
cats = client.factors.categories()
for c in cats.get("categories", cats.get("data", []))[:5]:
    print(f"  {c.get('category', c.get('name', ''))} ({c.get('count', '')} 个因子)")

section("3.3 因子截面数据 — factors.data('ep')")
fd = client.factors.data("ep")
pprint(fd)

section("3.4 因子详情 — factors.detail('ep')")
detail = client.factors.detail("ep")
pprint(detail)

section("3.5 单因子回测 — factors.backtest('ep')")
fb = client.factors.backtest("ep")
pprint(fb)

section("3.6 因子排行 — factors.top_bottom('ep', top_n=5)")
tb = client.factors.top_bottom("ep", top_n=5)
pprint(tb)


# ============================================================
# 4. AI 分析 (client.ai) — standard 权限
# ============================================================

section("4.1 AI 智能搜索 — ai.search('新能源')")
ai_search = client.ai.search(q="新能源", limit=3)
pprint(ai_search)

section("4.2 AI 估值分析 — ai.valuation() [standard 模式]")
print("  (耗时约 10-30 秒)")
valuation = client.ai.valuation(TS_CODE, mode="standard")
print(f"  估值评级: {valuation.get('rating', valuation.get('summary', ''))}")
pprint(valuation)

section("4.3 AI 综合评价 — ai.comprehensive()")
print("  (耗时约 10-30 秒)")
comp = client.ai.comprehensive(TS_CODE, mode="standard")
pprint(comp)

section("4.4 AI 趋势识别 — ai.trend()")
trend = client.ai.trend(TS_CODE)
pprint(trend)

# 注意: batch 和 report 接口耗时较长，按需使用
# section("4.5 AI 批量分析 — ai.batch()")
# batch = client.ai.batch(["000001.SZ", "600000.SH"], analysis_types=["valuation"])
# pprint(batch)

# section("4.6 AI 分析报告 — ai.report()")
# report = client.ai.report("valuation", TS_CODE)
# pprint(report)


# ============================================================
# 5. 回测系统 (client.backtest) — advanced 权限
# ============================================================

section("5.1 运行回测 — backtest.run()")
print("  (耗时约 30-120 秒)")
bt_result = client.backtest.run(
    factors=[
        {"name": "ep", "weight": 0.5},
        {"name": "momentum_20d", "weight": 0.5},
    ],
    start_date="2025-06-01",
    end_date="2026-01-01",
    top_n=20,
    timeout=300,
)
run_id = bt_result.get("run_id", "")
print(f"  回测ID: {run_id}")
print(f"  年化收益: {bt_result.get('annual_return', '')}  夏普比: {bt_result.get('sharpe_ratio', '')}")

section("5.2 查询回测结果 — backtest.result()")
if run_id:
    saved = client.backtest.result(run_id)
    pprint(saved)


# ============================================================
# 6. 多智能体策略 (client.agent) — advanced 权限
# ============================================================

section("6.1 策略配置 — agent.strategy_spec()")
spec = client.agent.strategy_spec()
pprint(spec)

section("6.2 市场状态检测 — agent.regime()")
regime = client.agent.regime()
print(f"  市场状态: {regime.get('regime', regime.get('state', ''))}")
pprint(regime)

# 注意: agent.run() 和 agent.llm_decision() 耗时较长
# section("6.3 运行多智能体选股 — agent.run()")
# agent_result = client.agent.run(timeout=300)
# pprint(agent_result)

# section("6.4 LLM 决策系统 — agent.llm_decision()")
# decision = client.agent.llm_decision(timeout=600)
# pprint(decision)


# ============================================================
# 7. 因子实验室 (client.factorlab) — advanced 权限
# ============================================================

section("7.1 查看待审核因子 — factorlab.reviews()")
reviews = client.factorlab.reviews()
pprint(reviews)

# 注意: generate 耗时较长
# section("7.2 AI 生成因子 — factorlab.generate()")
# gen = client.factorlab.generate(prompt="高ROE低波动因子", timeout=300)
# pprint(gen)

# section("7.3 审批因子 — factorlab.approve() / reject()")
# client.factorlab.approve("factor_xxx.py")
# client.factorlab.reject("factor_xxx.py")


# ============================================================
# 8. AI 对话 (client.chat) — advanced 权限
# ============================================================

section("8.1 流式对话 — chat.stream()")
print("  AI回复: ", end="")
session_id = None
for event in client.chat.stream("简要分析一下今天A股市场走势", timeout=60):
    if event.get("type") == "token":
        print(event["content"], end="", flush=True)
    elif event.get("type") == "done":
        session_id = event.get("session_id", "")
print()
print(f"  Session ID: {session_id}")

section("8.2 一次性对话 — chat.send()")
reply = client.chat.send("平安银行最近表现如何？", timeout=60)
print(f"  AI回复: {reply[:200]}...")

section("8.3 会话列表 — chat.sessions()")
sessions = client.chat.sessions()
pprint(sessions)

# section("8.4 会话详情 — chat.session_detail()")
# if session_id:
#     detail = client.chat.session_detail(session_id)
#     pprint(detail)

# section("8.5 删除会话 — chat.delete_session()")
# if session_id:
#     client.chat.delete_session(session_id)
#     print("  已删除")


# ============================================================
# 9. 新闻智能 (client.news) — advanced 权限
# ============================================================

section("9.1 新闻仪表盘 — news.dashboard()")
dashboard = client.news.dashboard()
pprint(dashboard)

section("9.2 新闻列表 — news.articles(category='macro', limit=3)")
articles = client.news.articles(category="macro", limit=3)
for a in articles.get("data", articles.get("articles", []))[:3]:
    print(f"  [{a.get('source_name', '')}] {a.get('title', '')}")

section("9.3 个股新闻信号 — news.signals(ts_code='000001.SZ')")
signals = client.news.signals(ts_code=TS_CODE)
pprint(signals)


# ============================================================
# 10. 数据表发现 (client.schema) — advanced 权限
# ============================================================

section("10.1 数据表列表 — schema.tables()")
tables = client.schema.tables(database="sagax_astock")
for t in tables.get("data", tables.get("tables", []))[:5]:
    print(f"  {t.get('database', '')}.{t.get('table', '')}  行数: {t.get('rows', '')}  大小: {t.get('size', '')}")

section("10.2 表详情 — schema.table_detail('sagax_astock', 'price_data')")
td = client.schema.table_detail("sagax_astock", "price_data")
pprint(td)


# ████████████████████████████████████████████████████████████
#                      期 货 接 口
# ████████████████████████████████████████████████████████████


# ============================================================
# 11. 期货市场数据 (client.futures)
# ============================================================

SYMBOL = "rb2510"  # 螺纹钢

section("11.1 期货市场概览 — futures.overview()")
f_overview = client.futures.overview()
print(f"  活跃合约数: {f_overview.get('active_count', '')}")
pprint(f_overview)

section("11.2 主力合约行情 — futures.indices()")
f_indices = client.futures.indices()
pprint(f_indices)

section("11.3 分交易所行情 — futures.sectors()")
f_sectors = client.futures.sectors()
pprint(f_sectors)

section("11.4 期货涨幅榜 — futures.gainers(limit=5)")
f_gainers = client.futures.gainers(limit=5)
pprint(f_gainers)

section("11.5 期货跌幅榜 — futures.losers(limit=5)")
f_losers = client.futures.losers(limit=5)
pprint(f_losers)

section("11.6 市场异动扫描 — futures.market_scan()")
scan = client.futures.market_scan()
pprint(scan)

section("11.7 合约列表 — futures.contracts(exchange='SHFE', main_only=True)")
f_contracts = client.futures.contracts(exchange="SHFE", main_only=True, per_page=5)
pprint(f_contracts)

section("11.8 合约搜索 — futures.search('螺纹钢')")
f_search = client.futures.search("螺纹钢")
for r in f_search.get("results", f_search.get("data", []))[:5]:
    print(f"  {r.get('ts_code', r.get('symbol', ''))} {r.get('name', '')}")

section("11.9 合约基本信息 — futures.basic()")
f_basic = client.futures.basic(SYMBOL)
print(f"  交易所: {f_basic.get('exchange', '')}  合约乘数: {f_basic.get('multiplier', '')}  最小变动: {f_basic.get('price_tick', '')}")

section("11.10 最新报价 — futures.price()")
f_price = client.futures.price(SYMBOL)
print(f"  最新价: {f_price.get('close', '')}  涨跌: {f_price.get('change', '')}  持仓量: {f_price.get('open_interest', '')}")

section("11.11 期货日K线 — futures.daily(days=5)")
f_daily = client.futures.daily(SYMBOL, days=5)
for row in f_daily.get("daily", f_daily.get("data", []))[:5]:
    print(f"  {row.get('trade_date', '')}  O:{row.get('open','')}  H:{row.get('high','')}  L:{row.get('low','')}  C:{row.get('close','')}  V:{row.get('volume', row.get('vol',''))}")

section("11.12 技术指标 — futures.indicators()")
f_ind = client.futures.indicators(SYMBOL)
pprint(f_ind)

section("11.13 最新技术指标 — futures.indicators_latest()")
f_ind_l = client.futures.indicators_latest(SYMBOL)
pprint(f_ind_l)

section("11.14 期货5min K线 — futures.kline(period='5min', limit=5)")
f_kline = client.futures.kline(SYMBOL, period="5min", limit=5)
for row in f_kline.get("kline", f_kline.get("data", []))[:5]:
    print(f"  {row.get('datetime', '')}  O:{row.get('open','')}  H:{row.get('high','')}  L:{row.get('low','')}  C:{row.get('close','')}")

section("11.15 期货统一K线 — futures.kline_unified(freq='daily', limit=5)")
f_ku = client.futures.kline_unified(SYMBOL, freq="daily", limit=5)
pprint(f_ku)


# ████████████████████████████████████████████████████████████
#                      错 误 处 理
# ████████████████████████████████████████████████████████████

section("12. 错误处理示例")

# 12.1 认证错误
print("  12.1 AuthError (错误的 API Key):")
try:
    bad_client = SagaxClient(api_key="wrong_key", secret_key="wrong_secret")
    bad_client.market.overview()
except AuthError as e:
    print(f"    捕获 AuthError: {e}")
except Exception as e:
    print(f"    捕获 {type(e).__name__}: {e}")

# 12.2 Not Found
print("\n  12.2 NotFoundError (不存在的股票):")
try:
    client.stock.basic("999999.XX")
except NotFoundError as e:
    print(f"    捕获 NotFoundError: {e}")
except Exception as e:
    print(f"    捕获 {type(e).__name__}: {e}")

# 12.3 Rate Limit
print("\n  12.3 RateLimitError (SDK 自动重试最多 3 次):")
print("    SDK 内置自动重试机制，遇到 429 会自动等待并重试")


# ============================================================
print(f"\n{'='*60}")
print("  全部接口演示完成!")
print(f"{'='*60}")
