ZhuLinsen/daily_stock_analysis · error · Error
选股功能不可用。请检查策略配置、数据依赖和服务日志。
Error message
选股功能不可用。请检查策略配置、数据依赖和服务日志。
What it means
Raised inside quantity replay (portfolio_service.py:765) when a historical sell event exceeds the running quantity_held at that point in the ordered event stream. This is the same oversell contract as the write-time check, but detected during replay of already-stored events, e.g. when computing a snapshot; PortfolioOversellError carries the event's symbol, date, and quantities.
Source
Thrown at apps/dsa-web/src/api/screening.ts:460
`/api/v1/screening/hotspots/${encodeURIComponent(payload.topic)}`,
{
params: {
provider: payload.provider || 'akshare',
refresh: payload.refresh ?? false,
include_search: payload.includeSearch ?? false,
},
timeout: SCREENING_REQUEST_TIMEOUT_MS,
},
);
return toCamelCase<ScreeningHotspotDetail>(response.data);
},
async enable(): Promise<void> {
await setScreeningEnabled('true');
try {
const status = await screeningApi.getStatus();
if (!status.available) {
throw new Error('选股功能不可用。请检查策略配置、数据依赖和服务日志。');
}
} catch (error) {
try {
await setScreeningEnabled('false');
} catch {
// Preserve the original availability/status failure for the caller.
}
throw error;
}
},
};
View on GitHub (pinned to 5159bd72e8)
Solutions
- Reconstruct a consistent timeline: ensure for each symbol every sell date has cumulative buys+splits covering it
- Restore or re-add the deleted/edited buy events, or delete the orphaned sells if they were wrong
- Insert the missing split_adjustment events so historical quantities scale correctly
- Import in chronological order and never mutate stored event dates directly in the DB
Example fix
# before # sell imported with date before its buy svc.add_trade(account_id=1, symbol="AAPL", side="sell", quantity=10, trade_date=date(2025,1,1), ...) svc.add_trade(account_id=1, symbol="AAPL", side="buy", quantity=10, trade_date=date(2024,12,31), ...) # after svc.add_trade(account_id=1, symbol="AAPL", side="buy", quantity=10, trade_date=date(2024,12,31), ...) svc.add_trade(account_id=1, symbol="AAPL", side="sell", quantity=10, trade_date=date(2025,1,1), ...)
Defensive patterns
Strategy: try-catch
Validate before calling
def timeline_consistent(svc, account_id, symbol):
held = 0.0
for ev in svc.query_trades(account_id=account_id, symbol=symbol, page=1, page_size=10000)["items"]:
held += ev["quantity"] if ev["side"] == "buy" else -ev["quantity"]
if held < -1e-8:
return False
return True Type guard
from src.services.portfolio_service import PortfolioOversellError
def is_oversell(exc: Exception) -> bool:
return isinstance(exc, PortfolioOversellError) Try / catch
from src.services.portfolio_service import PortfolioOversellError
try:
svc.get_snapshot(account_id=a)
except PortfolioOversellError as exc:
# exc.symbol / exc.trade_date pinpoint the first inconsistent sell
quarantine_event(exc.symbol, exc.trade_date); svc.get_snapshot(account_id=a) Prevention
- Import events in chronological order; never re-date stored events
- Do not delete or edit buys via direct DB access
- Insert split events before the sells that depend on them
- Verify same-day buy-then-sell ordering after timezone conversion
When it happens
Trigger: Deleting or re-dating a buy after sells were recorded; inserting a sell with an earlier trade_date than its covering buy; a missing split_adjustment so historical holdings are understated; importing an out-of-order history where an early sell is replayed before its buy. Because writes are validated at insert time, hitting this at replay usually means the event timeline changed after the fact.
Common situations: Manual edits to trade dates; deletion of a buy via direct DB access; import jobs inserting events in reverse-chronological batches with later backfills; timezone handling that shifts a buy's date to after a same-day sell.
Related errors
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/244c090d1715bbe4.
Report an issue: GitHub.