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"]))
