Skip to content

Commit d7c919d

Browse files
committed
fix(review-feedback-1245): address latest review comments
1 parent 72d0946 commit d7c919d

2 files changed

Lines changed: 60 additions & 7 deletions

File tree

src/analyzer.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,8 @@ def stabilize_decision_with_structure(
646646
_first_list_value(trend_dict.get("resistance_levels")),
647647
)
648648
flow_bias = _capital_flow_bias(fundamental_context)
649+
if flow_bias == "unavailable":
650+
return
649651
decision_type = infer_decision_type_from_advice(
650652
getattr(result, "decision_type", ""),
651653
default=getattr(result, "decision_type", "hold") or "hold",
@@ -808,24 +810,32 @@ def _first_numeric_value(*values: Any) -> Optional[float]:
808810

809811
def _capital_flow_bias(fundamental_context: Optional[Dict[str, Any]]) -> str:
810812
if not isinstance(fundamental_context, dict):
811-
return "neutral"
813+
return "unavailable"
812814
block = fundamental_context.get("capital_flow")
813815
if not isinstance(block, dict):
814-
return "neutral"
816+
return "unavailable"
817+
if block.get("status") == "not_supported":
818+
return "unavailable"
815819
data = block.get("data") if isinstance(block.get("data"), dict) else block
816820
stock_flow = data.get("stock_flow") if isinstance(data, dict) else None
817-
if not isinstance(stock_flow, dict):
818-
return "neutral"
821+
if not isinstance(stock_flow, dict) or not stock_flow:
822+
return "unavailable"
819823

820824
def _flow_direction(value: Optional[float]) -> Optional[str]:
821825
if value is None or value == 0:
822826
return None
823827
return "inflow" if value > 0 else "outflow"
824828

829+
numeric_values = [
830+
_coerce_numeric_value(stock_flow.get("main_net_inflow")),
831+
_coerce_numeric_value(stock_flow.get("inflow_5d")),
832+
_coerce_numeric_value(stock_flow.get("inflow_10d")),
833+
]
834+
if all(value is None for value in numeric_values):
835+
return "unavailable"
836+
825837
ordered_signals = [
826-
_flow_direction(_coerce_numeric_value(stock_flow.get("main_net_inflow"))),
827-
_flow_direction(_coerce_numeric_value(stock_flow.get("inflow_5d"))),
828-
_flow_direction(_coerce_numeric_value(stock_flow.get("inflow_10d"))),
838+
_flow_direction(value) for value in numeric_values
829839
]
830840
directions = {signal for signal in ordered_signals if signal is not None}
831841
if not directions or len(directions) > 1:

tests/test_decision_stability.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ def _fund_flow(main: float, five_day: float = 0.0, ten_day: float = 0.0) -> dict
5252
}
5353

5454

55+
def _unsupported_fund_flow() -> dict:
56+
return {"capital_flow": {"status": "not_supported", "data": {}}}
57+
58+
59+
def test_capital_flow_bias_is_unavailable_when_stock_flow_data_is_missing() -> None:
60+
assert _capital_flow_bias(_unsupported_fund_flow()) == "unavailable"
61+
assert _capital_flow_bias({"capital_flow": {"status": "ok", "data": {}}}) == "unavailable"
62+
63+
5564
def test_capital_flow_bias_is_neutral_when_missing_main_windows_conflict() -> None:
5665
context = {
5766
"capital_flow": {
@@ -115,6 +124,40 @@ def test_downgrades_buy_mid_range_with_neutral_fund_flow() -> None:
115124
assert "资金流不明确" in result.risk_warning
116125

117126

127+
def test_skips_calibration_when_capital_flow_is_unavailable() -> None:
128+
buy_result = _result(
129+
decision_type="buy",
130+
operation_advice="买入",
131+
score=66,
132+
current_price=32.0,
133+
)
134+
sell_result = _result(
135+
decision_type="sell",
136+
operation_advice="卖出",
137+
score=30,
138+
current_price=30.4,
139+
change_pct=-2.1,
140+
)
141+
142+
stabilize_decision_with_structure(
143+
buy_result,
144+
SimpleNamespace(support_levels=[30.0], resistance_levels=[34.0]),
145+
_unsupported_fund_flow(),
146+
)
147+
stabilize_decision_with_structure(
148+
sell_result,
149+
SimpleNamespace(support_levels=[30.0], resistance_levels=[34.0]),
150+
_unsupported_fund_flow(),
151+
)
152+
153+
assert buy_result.decision_type == "buy"
154+
assert buy_result.operation_advice == "买入"
155+
assert "decision_stability" not in buy_result.dashboard
156+
assert sell_result.decision_type == "sell"
157+
assert sell_result.operation_advice == "卖出"
158+
assert "decision_stability" not in sell_result.dashboard
159+
160+
118161
def test_downgrades_sell_near_support_without_sustained_outflow() -> None:
119162
result = _result(
120163
decision_type="sell",

0 commit comments

Comments
 (0)