跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://docs.tickflow.org/llms.txt

Use this file to discover all available pages before exploring further.

本页仅收录快速开始未涉及的进阶用法。基础用法(K 线获取、实时行情、标的信息、标的池、财务数据等)请先参阅快速开始。

K 线进阶

按时间范围查询

import datetime
from tickflow import TickFlow

tf = TickFlow(api_key="your-api-key")

start = int(datetime.datetime(2024, 1, 1).timestamp() * 1000)
end = int(datetime.datetime(2024, 12, 31).timestamp() * 1000)

df = tf.klines.get(
    "600000.SH",
    period="1d",
    start_time=start,
    end_time=end,
    count=10000,
    as_dataframe=True
)
print(f"获取到 {len(df)} 根 K 线")
print(df.tail())

批量获取大量股票

批量接口自动将标的列表分批并发请求。默认每批 100 个标的,可通过 batch_size 参数调整。
instruments = tf.exchanges.get_instruments("SH")
symbols = [inst["symbol"] for inst in instruments]
print(f"共 {len(symbols)} 只股票")

dfs = tf.klines.batch(
    symbols,
    period="1d",
    count=20,
    as_dataframe=True,
    show_progress=True,
    max_workers=5
)
print(f"成功获取 {len(dfs)} 只股票的数据")

计算技术指标

import pandas as pd

df = tf.klines.get("600000.SH", period="1d", count=100, as_dataframe=True)

# 均线
df["ma5"] = df["close"].rolling(5).mean()
df["ma20"] = df["close"].rolling(20).mean()

# MACD
exp1 = df["close"].ewm(span=12, adjust=False).mean()
exp2 = df["close"].ewm(span=26, adjust=False).mean()
df["macd"] = exp1 - exp2
df["signal"] = df["macd"].ewm(span=9, adjust=False).mean()

print(df[["close", "ma5", "ma20", "macd", "signal"]].tail())

日内 VWAP 计算

df_5m = tf.klines.intraday("600000.SH", period="5m", as_dataframe=True)
df_5m["vwap"] = (df_5m["amount"] / df_5m["volume"]).round(2)
print(df_5m[["trade_time", "close", "vwap"]].tail())

计算日 K 换手率

结合日 K 线的成交量和股本表的流通股本,计算每日换手率。由于流通股本会随时间变动(增发、回购等),使用 merge_asof 为每根 K 线匹配当时有效的流通股本。
import pandas as pd
from tickflow import TickFlow

tf = TickFlow(api_key="your-api-key")

symbol = "600000.SH"

kdf = tf.klines.get(symbol, period="1d", count=2000, as_dataframe=True)
sdf = tf.financials.shares([symbol], as_dataframe=True)

# 转为日期类型用于 merge_asof
kdf["date"] = pd.to_datetime(kdf["trade_date"])
sdf["date"] = pd.to_datetime(sdf["period_end"])

merged = pd.merge_asof(
    kdf.sort_values("date"),
    sdf[["date", "float_shares"]].sort_values("date"),
    on="date",
    direction="backward",
)

# A股 volume 单位为手(1 手 = 100 股),换手率 = volume * 100 / float_shares
merged["turnover_rate"] = (merged["volume"] * 100 / merged["float_shares"]).round(4)
merged["turnover_rate%"] = merged["turnover_rate"] * 100

print(merged[["trade_date", "close", "volume", "float_shares", "turnover_rate", "turnover_rate%"]].head(10))
print(merged[["trade_date", "close", "volume", "float_shares", "turnover_rate", "turnover_rate%"]].tail(10))
输出示例
   trade_date     close   volume  float_shares  turnover_rate  turnover_rate%
0  2018-01-26  9.864605  2184196  2.810376e+10         0.0078            0.78
1  2018-01-29  9.901386  1537831  2.810376e+10         0.0055            0.55
2  2018-01-30  9.643920  1078040  2.810376e+10         0.0038            0.38
3  2018-01-31  9.688057  1177032  2.810376e+10         0.0042            0.42
4  2018-02-01  9.783687  1735733  2.810376e+10         0.0062            0.62
5  2018-02-02  9.665989   717967  2.810376e+10         0.0026            0.26
6  2018-02-05  9.923454  1501496  2.810376e+10         0.0053            0.53
7  2018-02-06  9.916098  2443589  2.810376e+10         0.0087            0.87
8  2018-02-07  9.894030  2007701  2.810376e+10         0.0071            0.71
9  2018-02-08  9.636564  1094268  2.810376e+10         0.0039            0.39
      trade_date  close  volume  float_shares  turnover_rate  turnover_rate%
1990  2026-04-16  10.00  437023  3.330584e+10         0.0013            0.13
1991  2026-04-17   9.86  579330  3.330584e+10         0.0017            0.17
1992  2026-04-20   9.78  681169  3.330584e+10         0.0020            0.20
1993  2026-04-21   9.72  728490  3.330584e+10         0.0022            0.22
1994  2026-04-22   9.61  685905  3.330584e+10         0.0021            0.21
1995  2026-04-23   9.54  806247  3.330584e+10         0.0024            0.24
1996  2026-04-24   9.45  848590  3.330584e+10         0.0025            0.25
1997  2026-04-27   9.36  872815  3.330584e+10         0.0026            0.26
1998  2026-04-28   9.37  594550  3.330584e+10         0.0018            0.18
1999  2026-04-29   9.38  614950  3.330584e+10         0.0018            0.18

行情筛选

涨跌幅排行

df = tf.quotes.get(universes=["CN_Equity_A"], as_dataframe=True)
df["change_pct"] = (df["last_price"] - df["prev_close"]) / df["prev_close"] * 100

print("涨幅榜 Top 10:")
print(df.nlargest(10, "change_pct")[["symbol", "last_price", "change_pct"]])

print("\n跌幅榜 Top 10:")
print(df.nsmallest(10, "change_pct")[["symbol", "last_price", "change_pct"]])

多条件筛选

df = tf.quotes.get(universes=["CN_Equity_A"], as_dataframe=True)
df["change_pct"] = (df["last_price"] - df["prev_close"]) / df["prev_close"] * 100

# 涨停股(涨幅 >= 9.9%)
limit_up = df[df["change_pct"] >= 9.9]
print(f"涨停股数量: {len(limit_up)}")

# 放量上涨:成交额 > 10 亿且涨幅 > 3%
strong = df[(df["amount"] > 1e9) & (df["change_pct"] > 3)]
print(f"放量上涨股票: {len(strong)}")

涨停 / 跌停筛选

上面的多条件筛选用涨跌幅百分比粗略估算涨停,但 A 股存在 10%、20%(创业板/科创板)、30%(北交所)等多种涨跌幅限制,按固定百分比无法覆盖所有情况。更精确的做法是用 instruments 接口返回的 ext.limit_up / ext.limit_down(当日涨停价 / 跌停价)与 last_price 直接比较。 下面的示例内置了 instruments 自动缓存:首次调用时加载,之后每天 09:10 自动刷新一次(A 股盘前涨跌停价会更新),无需手动管理。
from datetime import datetime
from zoneinfo import ZoneInfo

from tickflow import TickFlow

tf = TickFlow(api_key="your-api-key")

_TZ = ZoneInfo("Asia/Shanghai")
_inst_cache: dict[str, dict] = {}
_refreshed_date = None


def _ensure_instruments():
    """启动时加载,之后每天 09:10 后自动刷新一次。"""
    global _inst_cache, _refreshed_date

    now = datetime.now(_TZ)
    today = now.date()
    after_0910 = now.hour > 9 or (now.hour == 9 and now.minute >= 10)

    if _inst_cache and not (after_0910 and _refreshed_date != today):
        return

    symbols = (tf.universes.get("CN_Equity_A") or {}).get("symbols", [])
    instruments = tf.instruments.batch(symbols=symbols) or []
    _inst_cache = {i["symbol"]: i for i in instruments if i and i.get("symbol")}
    _refreshed_date = today
    print(f"instruments 已刷新: {len(_inst_cache)} 只")


def get_limit_stocks():
    """返回 (涨停 DataFrame, 跌停 DataFrame)。"""
    _ensure_instruments()

    df = tf.quotes.get(universes=["CN_Equity_A"], as_dataframe=True)

    def _match(row, key):
        inst = _inst_cache.get(row["symbol"])
        if not inst:
            return False
        price = (inst.get("ext") or {}).get(key)
        return price is not None and abs(row.get("last_price", 1e-3) - price) < 1e-3

    df["is_limit_up"] = df.apply(lambda r: _match(r, "limit_up"), axis=1)
    df["is_limit_down"] = df.apply(lambda r: _match(r, "limit_down"), axis=1)

    return df[df["is_limit_up"]], df[df["is_limit_down"]]


up, down = get_limit_stocks()

print(f"涨停: {len(up)} 只")
print(up[["symbol", "ext.name", "last_price"]].to_string(index=False))

print(f"\n跌停: {len(down)} 只")
print(down[["symbol", "ext.name", "last_price"]].to_string(index=False))
如需持续监控,只需在循环中反复调用 get_limit_stocks(),缓存会自动管理:
import time

while True:
    up, down = get_limit_stocks()
    now = datetime.now(_TZ).strftime("%H:%M:%S")
    print(f"[{now}] 涨停 {len(up)} 只, 跌停 {len(down)} 只")
    time.sleep(3)

除权因子分析

对比除权前后价格

import datetime

symbol = "600519.SH"

factors_df = tf.klines.ex_factors([symbol], as_dataframe=True)
latest_factor = factors_df.iloc[-1]
print(f"最近除权日: {latest_factor['trade_date']}, 因子: {latest_factor['ex_factor']:.6f}")

ex_date = int(datetime.datetime.strptime(latest_factor["trade_date"], "%Y-%m-%d").timestamp() * 1000)
start = ex_date - 10 * 86400_000
end = ex_date + 10 * 86400_000

df_raw = tf.klines.get(symbol, start_time=start, end_time=end, adjust="none", as_dataframe=True)
df_qfq = tf.klines.get(symbol, start_time=start, end_time=end, adjust="forward", as_dataframe=True)

print(f"\n不复权价格:")
print(df_raw[["trade_date", "close"]].to_string(index=False))
print(f"\n前复权价格:")
print(df_qfq[["trade_date", "close"]].to_string(index=False))

美股 & 港股

行情与 K 线

# 美股行情
us_quotes = tf.quotes.get(symbols=["AAPL.US", "MSFT.US", "TSLA.US"], as_dataframe=True)
print(us_quotes)

# 港股行情
hk_quotes = tf.quotes.get(symbols=["00700.HK", "09988.HK"], as_dataframe=True)
print(hk_quotes)

# 美股日 K 线(支持前复权/后复权)
df_us = tf.klines.get("AAPL.US", period="1d", count=100, as_dataframe=True)
print(df_us.tail())

# 批量获取
us_symbols = ["AAPL.US", "MSFT.US", "GOOGL.US", "AMZN.US", "TSLA.US"]
dfs = tf.klines.batch(us_symbols, period="1d", count=100, as_dataframe=True, show_progress=True)
for symbol, df in dfs.items():
    print(f"{symbol}: 最新收盘 {df['close'].iloc[-1]}")
美股和港股目前仅支持日线级别(1d、1w、1M、1Q、1Y),暂不支持分钟 K 线和日内分时。

异步高并发

并发获取与分析

import asyncio
from tickflow import AsyncTickFlow


async def fetch_stock_data(tf: AsyncTickFlow, symbol: str) -> dict:
    df = await tf.klines.get(symbol, period="1d", count=60, as_dataframe=True)
    df["ma20"] = df["close"].rolling(20).mean()
    latest = df.iloc[-1]
    return {
        "symbol": symbol,
        "price": latest["close"],
        "ma20": latest["ma20"],
        "above_ma20": latest["close"] > latest["ma20"],
    }

async def main():
    async with AsyncTickFlow(api_key="your-api-key") as tf:
        symbols = ["600000.SH", "600519.SH", "000001.SZ", "000858.SZ", "601318.SH"]
        results = await asyncio.gather(*[fetch_stock_data(tf, s) for s in symbols])
        for r in results:
            status = "站上" if r["above_ma20"] else "跌破"
            print(f"{r['symbol']}: {r['price']:.2f} ({status} MA20: {r['ma20']:.2f})")

asyncio.run(main())

定时监控行情

import asyncio
import datetime
from tickflow import AsyncTickFlow


async def monitor_quotes(symbols, interval=5):
    async with AsyncTickFlow(api_key="your-api-key") as tf:
        while True:
            quotes = await tf.quotes.get(symbols=symbols)
            print(f"\n--- {datetime.datetime.now().strftime('%H:%M:%S')} ---")
            for q in quotes:
                change = (q["last_price"] - q["prev_close"]) / q["prev_close"] * 100
                print(f"{q['symbol']}: {q['last_price']:.2f} ({change:+.2f}%)")
            await asyncio.sleep(interval)

asyncio.run(monitor_quotes(["600000.SH", "000001.SZ"]))