提交
This commit is contained in:
@@ -56,6 +56,10 @@ def _ma(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
return {"ma": ind.ma(df["close"], period=int(p["period"]))}
|
||||
|
||||
|
||||
def _vol_ratio(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
return {"vol_ratio": ind.vol_ratio(df["volume"], period=int(p["period"]))}
|
||||
|
||||
|
||||
def _boll(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
out = ind.bollinger(df["close"], period=int(p["period"]), std=float(p["std"]))
|
||||
return {"boll_upper": out["upper"], "boll_mid": out["mid"], "boll_lower": out["lower"]}
|
||||
@@ -75,6 +79,16 @@ def _pct_chg(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
return {"pct_chg": df["pct_chg"]}
|
||||
|
||||
|
||||
def _amplitude(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
# 当日振幅 %(通达信口径:(最高-最低)/昨收×100),依赖派生列 amplitude
|
||||
return {"amplitude": df["amplitude"]}
|
||||
|
||||
|
||||
def _turnover_rate(df: pd.DataFrame, p: dict) -> dict[str, pd.Series]:
|
||||
# 逐日换手率 %(candles.turnover 直读;ETF/缺数据日为 NaN,条件按 False 处理)
|
||||
return {"turnover_rate": df["turnover"]}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FamilyDef:
|
||||
label: str # 族中文标签(条件回显/表头)
|
||||
@@ -89,20 +103,24 @@ FAMILIES: dict[str, FamilyDef] = {
|
||||
"macd": FamilyDef("MACD", ("fast", "slow", "signal"), {"fast": 12, "slow": 26, "signal": 9}, 60, _macd),
|
||||
"rsi": FamilyDef("RSI", ("period",), {"period": 14}, 25, _rsi),
|
||||
"ma": FamilyDef("MA", ("period",), {"period": 20}, 25, _ma),
|
||||
"vol_ratio": FamilyDef("量比", ("period",), {"period": 5}, 10, _vol_ratio),
|
||||
"boll": FamilyDef("BOLL", ("period", "std"), {"period": 20, "std": 2}, 25, _boll),
|
||||
"zhixing": FamilyDef("知行", ("m1", "m2", "m3", "m4"),
|
||||
{"m1": 14, "m2": 28, "m3": 57, "m4": 114}, 114, _zhixing),
|
||||
"close": FamilyDef("收盘价", (), {}, 1, _close),
|
||||
"pct_chg": FamilyDef("日涨跌幅", (), {}, 1, _pct_chg),
|
||||
"amplitude": FamilyDef("当日振幅", (), {}, 2, _amplitude),
|
||||
"turnover_rate": FamilyDef("换手率", (), {}, 1, _turnover_rate),
|
||||
}
|
||||
|
||||
INDICATOR_FAMILY: dict[str, str] = {
|
||||
"kdj_k": "kdj", "kdj_d": "kdj", "kdj_j": "kdj",
|
||||
"macd_dif": "macd", "macd_dea": "macd", "macd_hist": "macd",
|
||||
"rsi": "rsi", "ma": "ma",
|
||||
"rsi": "rsi", "ma": "ma", "vol_ratio": "vol_ratio",
|
||||
"boll_upper": "boll", "boll_mid": "boll", "boll_lower": "boll",
|
||||
"zhixing_dkx": "zhixing", "zhixing_trend": "zhixing",
|
||||
"close": "close", "pct_chg": "pct_chg",
|
||||
"amplitude": "amplitude", "turnover_rate": "turnover_rate",
|
||||
}
|
||||
|
||||
_IND_SUFFIX = {"kdj_k": "K", "kdj_d": "D", "kdj_j": "J",
|
||||
@@ -317,23 +335,27 @@ async def _load_bars(session: AsyncSession, ts_codes: list[str],
|
||||
"""
|
||||
symbols = [plain_code(t) for t in ts_codes]
|
||||
stmt = select(
|
||||
Candle.symbol, Candle.ts, Candle.open, Candle.high, Candle.low, Candle.close,
|
||||
Candle.symbol, Candle.ts, Candle.open, Candle.high, Candle.low, Candle.close, Candle.volume,
|
||||
Candle.turnover,
|
||||
).where(Candle.timeframe == "1d", Candle.ts >= min_date, Candle.ts <= target_date)
|
||||
if len(symbols) <= 2000:
|
||||
stmt = stmt.where(Candle.symbol.in_(set(symbols)))
|
||||
rows = (await session.execute(stmt)).all()
|
||||
df = pd.DataFrame(rows, columns=["symbol", "trade_date", "open", "high", "low", "close"])
|
||||
df = pd.DataFrame(rows, columns=["symbol", "trade_date", "open", "high", "low", "close", "volume", "turnover"])
|
||||
if not df.empty and len(symbols) > 2000:
|
||||
df = df[df["symbol"].isin(set(symbols))]
|
||||
df = df.sort_values(["symbol", "trade_date"]).reset_index(drop=True)
|
||||
if df.empty:
|
||||
df["ts_code"] = pd.Series(dtype=object)
|
||||
df["pct_chg"] = pd.Series(dtype=object)
|
||||
df["amplitude"] = pd.Series(dtype=object)
|
||||
else:
|
||||
prev_close = df.groupby("symbol")["close"].shift(1)
|
||||
df["pct_chg"] = df.groupby("symbol")["close"].pct_change() * 100
|
||||
df["amplitude"] = (df["high"] - df["low"]) / prev_close * 100
|
||||
ts_map = {plain_code(t): t for t in ts_codes}
|
||||
df["ts_code"] = df["symbol"].map(ts_map)
|
||||
return df[["ts_code", "trade_date", "open", "high", "low", "close", "pct_chg"]]
|
||||
return df[["ts_code", "trade_date", "open", "high", "low", "close", "volume", "turnover", "pct_chg", "amplitude"]]
|
||||
|
||||
|
||||
def _f(v) -> float | None:
|
||||
|
||||
Reference in New Issue
Block a user