Skill: shawn92/ftshare-performance-data (version 1.0.0)

--- name: FTShare-ashare-performance-data description: A 股业绩大全技能集。覆盖业绩快报、业绩预告、现金流量表、利润表、资产负债表（单票历期与指定报告期全市场，market.ft.tech）。用户询问业绩快报、业绩预告、三表、单票或全市场某报告期时使用。 --- # FT A-share 业绩大全 Skills 本 skill 是 `FTShare-ashare-performance-data` 的**统一路由入口**。 根据用户问题，从下方「能力总览」匹配对应子 skill，然后通过 `run.py` 执行并解析响应。 > 所有接口均以 `https://market.ft.tech` 为基础域名，使用 HTTP GET。 --- ## 调用方式（唯一规则） `run.py` 与本文件（`SKILL.md`）位于同一目录。执行时： 1. 取本文件的绝对路径，将末尾 `/SKILL.md` 替换为 `/run.py`，得到 `<RUN_PY>` 。 2. 调用：`python <RUN_PY> <子skill名> [参数...]` ```bash # 示例（<RUN_PY> 为实际绝对路径） python <RUN_PY> stock-performance-express-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20 python <RUN_PY> stock-performance-express-single-stock-all-periods --stock-code 000001.SZ --page 1 --page-size 50 python <RUN_PY> stock-performance-forecast-all-stocks-specific-period --year 2025 --report-type annual --page 1 --page-size 20 python <RUN_PY> stock-performance-forecast-single-stock-all-periods --stock-code 000001.SZ --page 1 --page-size 50 python <RUN_PY> stock-cashflow-single-stock-all-periods --stock-code 000001.SZ python <RUN_PY> stock-cashflow-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20 python <RUN_PY> stock-income-single-stock-all-periods --stock-code 000001.SZ python <RUN_PY> stock-income-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20 python <RUN_PY> stock-balance-single-stock-all-periods --stock-code 000001.SZ python <RUN_PY> stock-balance-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20 ``` > `run.py` 内部通过 `__file__` 自定位，无论安装在何处都能正确找到各子 skill 的脚本。 --- ## 能力总览 ### 1. 业绩快报 / 业绩预告 - **[REDACTED_SECRET]**：单一报告期（如 2025Q2）全市场业绩快报列表（分页）。必填：`--year`、`--report-type`；可选 `--page`、`--page-size`。 - **[REDACTED_SECRET]**：单只股票历期业绩快报（分页）。必填：`--stock-code`；可选 `--page`、`--page-size`。 - **[REDACTED_SECRET]**：单一报告期全市场业绩预告列表（分页）。必填：`--year`、`--report-type`；可选 `--page`、`--page-size`。 - **[REDACTED_SECRET]**：单只股票历期业绩预告（分页）。必填：`--stock-code`；可选 `--page`、`--page-size`。 ### 2. 现金流量表 - **[REDACTED_SECRET]**：单只股票所有报告期现金流量表。必填：`--stock-code`。 - **[REDACTED_SECRET]**：指定报告期全市场现金流量表（分页）。必填：`--year`、`--report-type`、`--page`、`--page-size`。 ### 3. 利润表 - **[REDACTED_SECRET]**：单只股票所有报告期利润表。必填：`--stock-code`。 - **[REDACTED_SECRET]**：指定报告期全市场利润表（分页）。必填：`--year`、`--report-type`、`--page`、`--page-size`。 ### 4. 资产负债表 - **[REDACTED_SECRET]**：单只股票所有报告期资产负债表。必填：`--stock-code`。 - **[REDACTED_SECRET]**：指定报告期全市场资产负债表（分页）。必填：`--year`、`--report-type`、`--page`、`--page-size`。 --- ## 使用流程 1. **记录本文件绝对路径**，将 `/SKILL.md` 替换为 `/run.py` 得到 `<RUN_PY>`。 2. **理解用户意图**，从「能力总览」匹配对应子 skill 名称。 3. （可选）读取 `sub-skills/<子skill名>/SKILL.md` 了解接口详情与参数。 4. **执行**：`python <RUN_PY> <子skill名> [参数...]`，获取 JSON 输出。 5. **解析并输出**：以表格或要点形式展示给用户。 --- ## 子 skill 与用户问法示例 | 用户问法示例 | 子 skill 名 | |--------------|-------------| | 「2025 年二季报/半年报业绩快报」「指定报告期全市场业绩快报」 | `stock-performance-express-all-stocks-specific-period` | | 「某只股票历期业绩快报」 | `stock-performance-express-single-stock-all-periods` | | 「2025 年年报业绩预告」「指定报告期全市场业绩预告」 | `stock-performance-forecast-all-stocks-specific-period` | | 「某只股票历期业绩预告」 | `stock-performance-forecast-single-stock-all-periods` | | 「某只股票现金流量表」「历期现金流量表」 | `stock-cashflow-single-stock-all-periods` | | 「2025 年二季报全市场现金流量表」 | `stock-cashflow-all-stocks-specific-period` | | 「某只股票利润表」「历期利润表」 | `stock-income-single-stock-all-periods` | | 「2025 年二季报全市场利润表」 | `stock-income-all-stocks-specific-period` | | 「某只股票资产负债表」「历期资产负债表」 | `stock-balance-single-stock-all-periods` | | 「2025 年二季报全市场资产负债表」 | `stock-balance-all-stocks-specific-period` |

path: run.py
content: #!/usr/bin/env python3
"""
FTShare-ashare-performance-data 统一调度入口（业绩大全）。

用法：
    python run.py <subskill名> [handler参数...]

示例：
    python run.py stock-performance-express-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20
    python run.py stock-performance-express-single-stock-all-periods --stock-code 000001.SZ
    python run.py stock-cashflow-single-stock-all-periods --stock-code 000001.SZ
    python run.py stock-income-all-stocks-specific-period --year 2025 --report-type q2 --page 1 --page-size 20
    python run.py stock-balance-single-stock-all-periods --stock-code 000001.SZ
"""
import os
import runpy
import sys

SKILL_ROOT = os.path.dirname(os.path.abspath(__file__))


def _allowed_subskills():
    """仅允许 sub-skills 目录下存在 scripts/handler.py 的名称，防止路径遍历。"""
    sub_skills_dir = os.path.join(SKILL_ROOT, "sub-skills")
    allowed = set()
    if not os.path.isdir(sub_skills_dir):
        return allowed
    for name in os.listdir(sub_skills_dir):
        if os.path.isfile(os.path.join(sub_skills_dir, name, "scripts", "handler.py")):
            allowed.add(name)
    return allowed




def _execute_handler(handler: str, handler_args: list) -> int:
    """在当前进程执行 handler.py，避免 subprocess 告警。"""
    old_cwd = os.getcwd()
    old_argv = sys.argv[:]
    try:
        os.chdir(SKILL_ROOT)
        sys.argv = [handler] + handler_args
        runpy.run_path(handler, run_name="__main__")
        return 0
    except SystemExit as e:
        code = e.code
        if isinstance(code, int):
            return code
        return 1 if code else 0
    finally:
        sys.argv = old_argv
        os.chdir(old_cwd)

def main():
    sub_skills_dir = os.path.join(SKILL_ROOT, "sub-skills")
    allowed = _allowed_subskills()

    if len(sys.argv) < 2:
        print("用法: python run.py <subskill名> [参数...]", file=sys.stderr)
        print("\n可用 subskill：")
        for name in sorted(allowed):
            print(f"  {name}")
        sys.exit(1)

    subskill = sys.argv[1]
    if subskill not in allowed:
        print(f"错误：未找到 subskill '{subskill}'，或名称不合法。", file=sys.stderr)
        sys.exit(1)

    handler = os.path.join(sub_skills_dir, subskill, "scripts", "handler.py")

    exit_code = _execute_handler(handler, sys.argv[2:])
    sys.exit(exit_code)


if __name__ == "__main__":
    main()


path: sub-skills/stock-balance-all-stocks-specific-period/scripts/handler.py
content: #!/usr/bin/env python3
"""查询指定报告期全市场资产负债表（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"
VALID_REPORT_TYPES = ["q1", "q2", "q3", "annual"]


def main():
    parser = argparse.ArgumentParser(description="查询指定报告期全市场资产负债表（分页）")
    parser.add_argument("--year", type=int, required=True, help="报告所属年度，如 2025")
    parser.add_argument("--report-type", required=True, choices=VALID_REPORT_TYPES,
                        help="报告期类型：q1（一季报）/ q2（半年报）/ q3（三季报）/ annual（年报）")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=20, help="每页记录数（默认 20）")
    args = parser.parse_args()

    params = {
        "year": args.year,
        "report_type": args.report_type,
        "page": args.page,
        "page_size": args.page_size,
    }
    url = f"{BASE_URL}/data/api/v1/market/data/finance/balance?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-income-single-stock-all-periods/scripts/handler.py
content: #!/usr/bin/env python3
"""查询单只股票所有报告期的利润表"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"


def main():
    parser = argparse.ArgumentParser(description="查询单只股票历期利润表")
    parser.add_argument("--stock-code", required=True, help="股票代码，含市场后缀，如 603323.SH")
    args = parser.parse_args()

    params = {"stock_code": args.stock_code}
    url = f"{BASE_URL}/data/api/v1/market/data/finance/income?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-performance-express-all-stocks-specific-period/scripts/handler.py
content: #!/usr/bin/env python3
"""查询指定报告期所有股票业绩快报（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"
VALID_REPORT_TYPES = ["q1", "q2", "q3", "annual"]


def main():
    parser = argparse.ArgumentParser(description="查询指定报告期全市场业绩快报（分页）")
    parser.add_argument("--year", type=int, required=True, help="报告所属年度，如 2025")
    parser.add_argument("--report-type", required=True, choices=VALID_REPORT_TYPES,
                        help="报告期类型：q1（一季报）/ q2（半年报）/ q3（三季报）/ annual（年报）")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=20, help="每页记录数（默认 20）")
    args = parser.parse_args()

    params = {
        "year": args.year,
        "report_type": args.report_type,
        "page": args.page,
        "page_size": args.page_size,
    }
    url = f"{BASE_URL}/data/api/v1/market/data/finance/stock-performance-express?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-performance-express-single-stock-all-periods/scripts/handler.py
content: #!/usr/bin/env python3
"""查询单只股票所有报告期的业绩快报（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"


def main():
    parser = argparse.ArgumentParser(description="查询单只股票历期业绩快报（分页）")
    parser.add_argument("--stock-code", required=True, help="股票代码，含市场后缀，如 603323.SH")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=50, help="每页记录数（默认 50）")
    args = parser.parse_args()

    params = {"stock_code": args.stock_code, "page": args.page, "page_size": args.page_size}
    url = f"{BASE_URL}/data/api/v1/market/data/finance/stock-performance-express?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-cashflow-single-stock-all-periods/scripts/handler.py
content: #!/usr/bin/env python3
"""查询单只股票所有报告期的现金流量表"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"


def main():
    parser = argparse.ArgumentParser(description="查询单只股票历期现金流量表")
    parser.add_argument("--stock-code", required=True, help="股票代码，含市场后缀，如 603323.SH")
    args = parser.parse_args()

    params = {"stock_code": args.stock_code}
    url = f"{BASE_URL}/data/api/v1/market/data/finance/cashflow?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-income-all-stocks-specific-period/scripts/handler.py
content: #!/usr/bin/env python3
"""查询指定报告期全市场利润表（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"
VALID_REPORT_TYPES = ["q1", "q2", "q3", "annual"]


def main():
    parser = argparse.ArgumentParser(description="查询指定报告期全市场利润表（分页）")
    parser.add_argument("--year", type=int, required=True, help="报告所属年度，如 2025")
    parser.add_argument("--report-type", required=True, choices=VALID_REPORT_TYPES,
                        help="报告期类型：q1（一季报）/ q2（半年报）/ q3（三季报）/ annual（年报）")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=20, help="每页记录数（默认 20）")
    args = parser.parse_args()

    params = {
        "year": args.year,
        "report_type": args.report_type,
        "page": args.page,
        "page_size": args.page_size,
    }
    url = f"{BASE_URL}/data/api/v1/market/data/finance/income?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-cashflow-all-stocks-specific-period/scripts/handler.py
content: #!/usr/bin/env python3
"""查询指定报告期全市场现金流量表（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"
VALID_REPORT_TYPES = ["q1", "q2", "q3", "annual"]


def main():
    parser = argparse.ArgumentParser(description="查询指定报告期全市场现金流量表（分页）")
    parser.add_argument("--year", type=int, required=True, help="报告所属年度，如 2025")
    parser.add_argument("--report-type", required=True, choices=VALID_REPORT_TYPES,
                        help="报告期类型：q1（一季报）/ q2（半年报）/ q3（三季报）/ annual（年报）")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=20, help="每页记录数（默认 20）")
    args = parser.parse_args()

    params = {
        "year": args.year,
        "report_type": args.report_type,
        "page": args.page,
        "page_size": args.page_size,
    }
    url = f"{BASE_URL}/data/api/v1/market/data/finance/cashflow?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-performance-forecast-single-stock-all-periods/scripts/handler.py
content: #!/usr/bin/env python3
"""查询单只股票所有报告期的业绩预告（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"


def main():
    parser = argparse.ArgumentParser(description="查询单只股票历期业绩预告（分页）")
    parser.add_argument("--stock-code", required=True, help="股票代码，含市场后缀，如 603323.SH")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=50, help="每页记录数（默认 50）")
    args = parser.parse_args()

    params = {"stock_code": args.stock_code, "page": args.page, "page_size": args.page_size}
    url = f"{BASE_URL}/data/api/v1/market/data/finance/stock-performance-forecast?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-balance-single-stock-all-periods/scripts/handler.py
content: #!/usr/bin/env python3
"""查询单只股票所有报告期的资产负债表"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"


def main():
    parser = argparse.ArgumentParser(description="查询单只股票历期资产负债表")
    parser.add_argument("--stock-code", required=True, help="股票代码，含市场后缀，如 603323.SH")
    args = parser.parse_args()

    params = {"stock_code": args.stock_code}
    url = f"{BASE_URL}/data/api/v1/market/data/finance/balance?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


path: sub-skills/stock-performance-forecast-all-stocks-specific-period/scripts/handler.py
content: #!/usr/bin/env python3
"""查询指定报告期所有股票业绩预告（分页）"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
SAFE_URLOPENER = urllib.request.build_opener()

BASE_URL = "https://market.ft.tech"
VALID_REPORT_TYPES = ["q1", "q2", "q3", "annual"]


def main():
    parser = argparse.ArgumentParser(description="查询指定报告期全市场业绩预告（分页）")
    parser.add_argument("--year", type=int, required=True, help="报告所属年度，如 2025")
    parser.add_argument("--report-type", required=True, choices=VALID_REPORT_TYPES,
                        help="报告期类型：q1（一季报）/ q2（中报）/ q3（三季报）/ annual（年报）")
    parser.add_argument("--page", type=int, default=1, help="页码，从 1 开始（默认 1）")
    parser.add_argument("--page-size", type=int, default=20, help="每页记录数（默认 20）")
    args = parser.parse_args()

    params = {
        "year": args.year,
        "report_type": args.report_type,
        "page": args.page,
        "page_size": args.page_size,
    }
    url = f"{BASE_URL}/data/api/v1/market/data/finance/stock-performance-forecast?" + urllib.parse.urlencode(params)

    try:
        with SAFE_URLOPENER.open(url) as resp:
            data = json.loads(resp.read().decode())
        print(json.dumps(data, ensure_ascii=False, indent=2))
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP {e.code}: {body}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)