Compare commits
5 Commits
feature/is
...
f58d42fdb0
| Author | SHA1 | Date | |
|---|---|---|---|
| f58d42fdb0 | |||
|
|
0b20251de0 | ||
| bffe6e9288 | |||
|
|
0146d1bf8a | ||
| 497564e75c |
@@ -346,8 +346,10 @@ class GeminiClient:
|
||||
# Validate required fields
|
||||
if not all(k in data for k in ("action", "confidence", "rationale")):
|
||||
logger.warning("Missing fields in Gemini response — defaulting to HOLD")
|
||||
# Preserve raw text in rationale so prompt_override callers (e.g. pre_market_planner)
|
||||
# can extract their own JSON format from decision.rationale (#245)
|
||||
return TradeDecision(
|
||||
action="HOLD", confidence=0, rationale="Missing required fields"
|
||||
action="HOLD", confidence=0, rationale=raw
|
||||
)
|
||||
|
||||
action = str(data["action"]).upper()
|
||||
|
||||
@@ -179,8 +179,8 @@ class PromptOptimizer:
|
||||
# Minimal instructions
|
||||
prompt = (
|
||||
f"{market_name} trader. Analyze:\n{data_str}\n\n"
|
||||
'Return JSON: {"act":"BUY"|"SELL"|"HOLD","conf":<0-100>,"reason":"<text>"}\n'
|
||||
"Rules: act=BUY/SELL/HOLD, conf=0-100, reason=concise. No markdown."
|
||||
'Return JSON: {"action":"BUY"|"SELL"|"HOLD","confidence":<0-100>,"rationale":"<text>"}\n'
|
||||
"Rules: action=BUY/SELL/HOLD, confidence=0-100, rationale=concise. No markdown."
|
||||
)
|
||||
else:
|
||||
# Data only (for cached contexts where instructions are known)
|
||||
|
||||
@@ -133,7 +133,7 @@ class OverseasBroker:
|
||||
"AUTH": "",
|
||||
"EXCD": ranking_excd,
|
||||
"NDAY": "0",
|
||||
"GUBN": "1",
|
||||
"GUBN": "0", # 0=전체(상승+하락), 1=상승만 — 변동성 스캐너는 전체 필요
|
||||
"VOL_RANG": "0",
|
||||
}
|
||||
|
||||
|
||||
@@ -93,9 +93,21 @@ class TestMalformedJsonHandling:
|
||||
|
||||
def test_json_with_missing_fields_returns_hold(self, settings):
|
||||
client = GeminiClient(settings)
|
||||
decision = client.parse_response('{"action": "BUY"}')
|
||||
raw = '{"action": "BUY"}'
|
||||
decision = client.parse_response(raw)
|
||||
assert decision.action == "HOLD"
|
||||
assert decision.confidence == 0
|
||||
# rationale preserves raw so prompt_override callers (e.g. pre_market_planner)
|
||||
# can extract non-TradeDecision JSON from decision.rationale (#245)
|
||||
assert decision.rationale == raw
|
||||
|
||||
def test_non_trade_decision_json_preserves_raw_in_rationale(self, settings):
|
||||
"""Playbook JSON (no action/confidence/rationale) must be preserved for planner."""
|
||||
client = GeminiClient(settings)
|
||||
playbook_json = '{"market_outlook": "neutral", "stocks": []}'
|
||||
decision = client.parse_response(playbook_json)
|
||||
assert decision.action == "HOLD"
|
||||
assert decision.rationale == playbook_json
|
||||
|
||||
def test_json_with_invalid_action_returns_hold(self, settings):
|
||||
client = GeminiClient(settings)
|
||||
|
||||
@@ -124,7 +124,7 @@ class TestFetchOverseasRankings:
|
||||
assert "/uapi/overseas-stock/v1/ranking/updown-rate" in url
|
||||
assert params["EXCD"] == "NAS"
|
||||
assert params["NDAY"] == "0"
|
||||
assert params["GUBN"] == "1"
|
||||
assert params["GUBN"] == "0" # 0=전체(상승+하락), 변동성 스캐너에 필요
|
||||
assert params["VOL_RANG"] == "0"
|
||||
|
||||
overseas_broker._broker._auth_headers.assert_called_with("HHDFS76290000")
|
||||
|
||||
@@ -124,6 +124,10 @@ class TestPromptOptimizer:
|
||||
assert len(prompt) < 300
|
||||
assert "005930" in prompt
|
||||
assert "75000" in prompt
|
||||
# Keys must match parse_response expectations (#242)
|
||||
assert '"action"' in prompt
|
||||
assert '"confidence"' in prompt
|
||||
assert '"rationale"' in prompt
|
||||
|
||||
def test_build_compressed_prompt_no_instructions(self):
|
||||
"""Test compressed prompt without instructions."""
|
||||
|
||||
Reference in New Issue
Block a user