migration: preserve market insights slice
This commit is contained in:
+6
-140
@@ -8,8 +8,11 @@ from typing import Any
|
||||
|
||||
from backend.database import MIGRATIONS, MigrationRunner, SQLiteConnectionFactory
|
||||
from backend.features.accounts.repository import AccountRepositoryMixin
|
||||
from backend.features.auction.repository import AuctionRepositoryMixin
|
||||
from backend.features.dragon_tiger.repository import DragonTigerRepositoryMixin
|
||||
from backend.features.market.repository import MarketRepositoryMixin
|
||||
from backend.features.pools.repository import PoolRepositoryMixin
|
||||
from backend.features.popularity.repository import PopularityRepositoryMixin
|
||||
from backend.features.system.repository import SystemSettingsRepositoryMixin
|
||||
|
||||
|
||||
@@ -24,8 +27,11 @@ def _optional_float(value: Any) -> float | None:
|
||||
|
||||
class ReviewDatabase(
|
||||
AccountRepositoryMixin,
|
||||
AuctionRepositoryMixin,
|
||||
DragonTigerRepositoryMixin,
|
||||
MarketRepositoryMixin,
|
||||
PoolRepositoryMixin,
|
||||
PopularityRepositoryMixin,
|
||||
SystemSettingsRepositoryMixin,
|
||||
):
|
||||
def __init__(self, path: Path) -> None:
|
||||
@@ -839,24 +845,6 @@ class ReviewDatabase(
|
||||
return cursor.rowcount > 0
|
||||
|
||||
|
||||
def list_seat_aliases(self) -> dict[str, str]:
|
||||
with self.connect() as connection:
|
||||
rows = connection.execute("SELECT seat_name, alias FROM seat_aliases").fetchall()
|
||||
return {row["seat_name"]: row["alias"] for row in rows}
|
||||
|
||||
def save_seat_alias(self, seat_name: str, alias: str) -> None:
|
||||
now = datetime.now().astimezone().isoformat(timespec="seconds")
|
||||
with self.connect() as connection:
|
||||
connection.execute(
|
||||
"""
|
||||
INSERT INTO seat_aliases (seat_name, alias, updated_at)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT(seat_name) DO UPDATE SET
|
||||
alias = excluded.alias,
|
||||
updated_at = excluded.updated_at
|
||||
""",
|
||||
(seat_name, alias, now),
|
||||
)
|
||||
|
||||
def list_sector_phase_overrides(self) -> dict[str, str]:
|
||||
with self.connect() as connection:
|
||||
@@ -1056,44 +1044,6 @@ class ReviewDatabase(
|
||||
)
|
||||
return len(values)
|
||||
|
||||
def upsert_auction_factors(self, rows: list[dict[str, Any]]) -> int:
|
||||
values = []
|
||||
for row in rows:
|
||||
trade_date = str(row.get("trade_date") or "")
|
||||
ts_code = str(row.get("ts_code") or "")
|
||||
price = float(row.get("price") or 0)
|
||||
pre_close = float(row.get("pre_close") or 0)
|
||||
if not trade_date or not ts_code or price <= 0 or pre_close <= 0:
|
||||
continue
|
||||
values.append(
|
||||
(
|
||||
trade_date,
|
||||
ts_code,
|
||||
price,
|
||||
pre_close,
|
||||
(price / pre_close - 1) * 100,
|
||||
float(row.get("vol") or 0),
|
||||
float(row.get("amount") or 0),
|
||||
float(row.get("turnover_rate") or 0),
|
||||
float(row.get("volume_ratio") or 0),
|
||||
)
|
||||
)
|
||||
with self.connect() as connection:
|
||||
connection.executemany(
|
||||
"""
|
||||
INSERT INTO auction_factors
|
||||
(trade_date, ts_code, price, pre_close, change, vol, amount,
|
||||
turnover_rate, volume_ratio)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(trade_date, ts_code) DO UPDATE SET
|
||||
price=excluded.price, pre_close=excluded.pre_close,
|
||||
change=excluded.change, vol=excluded.vol, amount=excluded.amount,
|
||||
turnover_rate=excluded.turnover_rate,
|
||||
volume_ratio=excluded.volume_ratio
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return len(values)
|
||||
|
||||
def upsert_earnings_events(self, rows: list[dict[str, Any]]) -> int:
|
||||
values = [
|
||||
@@ -1130,84 +1080,7 @@ class ReviewDatabase(
|
||||
)
|
||||
return len(values)
|
||||
|
||||
def upsert_popularity_factors(self, rows: list[dict[str, Any]]) -> int:
|
||||
values = [
|
||||
(
|
||||
str(row.get("trade_date") or ""),
|
||||
str(row.get("ts_code") or ""),
|
||||
int(row["ths_rank"]) if row.get("ths_rank") not in (None, "") else None,
|
||||
int(row["dc_rank"]) if row.get("dc_rank") not in (None, "") else None,
|
||||
float(row.get("combined_score") or 0),
|
||||
int(row["rank_change"]) if row.get("rank_change") not in (None, "") else None,
|
||||
int(bool(row.get("dual_source"))),
|
||||
)
|
||||
for row in rows
|
||||
if row.get("trade_date") and row.get("ts_code")
|
||||
]
|
||||
with self.connect() as connection:
|
||||
connection.executemany(
|
||||
"""
|
||||
INSERT INTO popularity_factors
|
||||
(trade_date, ts_code, ths_rank, dc_rank, combined_score,
|
||||
rank_change, dual_source)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(trade_date, ts_code) DO UPDATE SET
|
||||
ths_rank=excluded.ths_rank,
|
||||
dc_rank=excluded.dc_rank,
|
||||
combined_score=excluded.combined_score,
|
||||
rank_change=excluded.rank_change,
|
||||
dual_source=excluded.dual_source
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return len(values)
|
||||
|
||||
def upsert_lhb_institutions(self, rows: list[dict[str, Any]]) -> int:
|
||||
grouped: dict[tuple[str, str], dict[str, float | int]] = {}
|
||||
for row in rows:
|
||||
trade_date = str(row.get("trade_date") or "")
|
||||
ts_code = str(row.get("ts_code") or "")
|
||||
seat_name = str(row.get("exalter") or row.get("seat_name") or "")
|
||||
if not trade_date or not ts_code or "机构专用" not in seat_name:
|
||||
continue
|
||||
group = grouped.setdefault(
|
||||
(trade_date, ts_code),
|
||||
{"net": 0.0, "buy": 0.0, "sell": 0.0, "seats": 0},
|
||||
)
|
||||
group["net"] = float(group["net"]) + float(row.get("net_buy") or row.get("net_amount") or 0)
|
||||
group["buy"] = float(group["buy"]) + float(row.get("buy") or row.get("buy_amount") or 0)
|
||||
group["sell"] = float(group["sell"]) + float(row.get("sell") or row.get("sell_amount") or 0)
|
||||
group["seats"] = int(group["seats"]) + 1
|
||||
values = [
|
||||
(trade_date, ts_code, item["net"], item["buy"], item["sell"], item["seats"])
|
||||
for (trade_date, ts_code), item in grouped.items()
|
||||
]
|
||||
with self.connect() as connection:
|
||||
connection.executemany(
|
||||
"""
|
||||
INSERT INTO lhb_institution_daily
|
||||
(trade_date, ts_code, net_buy_amount, buy_amount, sell_amount, seat_count)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(trade_date, ts_code) DO UPDATE SET
|
||||
net_buy_amount=excluded.net_buy_amount,
|
||||
buy_amount=excluded.buy_amount,
|
||||
sell_amount=excluded.sell_amount,
|
||||
seat_count=excluded.seat_count
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return len(values)
|
||||
|
||||
def auction_factor_dates(self, end_date: str = "", limit: int = 80) -> list[str]:
|
||||
where = "WHERE trade_date <= ?" if end_date else ""
|
||||
parameters: tuple[Any, ...] = (end_date, limit) if end_date else (limit,)
|
||||
with self.connect() as connection:
|
||||
rows = connection.execute(
|
||||
f"SELECT DISTINCT trade_date FROM auction_factors {where} "
|
||||
"ORDER BY trade_date DESC LIMIT ?",
|
||||
parameters,
|
||||
).fetchall()
|
||||
return [row["trade_date"] for row in reversed(rows)]
|
||||
|
||||
def daily_indicator_dates(self, end_date: str = "", limit: int = 400) -> list[str]:
|
||||
where = "WHERE trade_date <= ?" if end_date else ""
|
||||
@@ -1227,13 +1100,6 @@ class ReviewDatabase(
|
||||
).fetchall()
|
||||
return [str(row["end_date"]) for row in rows]
|
||||
|
||||
def auction_factors_for_date(self, trade_date: str) -> list[dict[str, Any]]:
|
||||
with self.connect() as connection:
|
||||
rows = connection.execute(
|
||||
"SELECT * FROM auction_factors WHERE trade_date = ? ORDER BY ts_code",
|
||||
(trade_date,),
|
||||
).fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
|
||||
def daily_bars_for_date(self, trade_date: str) -> list[dict[str, Any]]:
|
||||
with self.connect() as connection:
|
||||
|
||||
Reference in New Issue
Block a user