CRITICAL FIX: Blind Logs
This commit is contained in:
parent
66c9807ed8
commit
af82fd9601
|
|
@ -22,6 +22,9 @@ All notable changes to the **TradingAgents** project will be documented in this
|
||||||
- **Payload Size Error**: Implemented input truncation (max 9000 chars) in `memory.py`.
|
- **Payload Size Error**: Implemented input truncation (max 9000 chars) in `memory.py`.
|
||||||
- **Display Layer De-Anonymization**: Added `deanonymize_text` to `TickerAnonymizer` and patched `cli/main.py` to reverse-map "ASSET_XXX" to real company names in the final report, effectively resolving "[Company Name]" placeholders for the user while keeping the internal system blind.
|
- **Display Layer De-Anonymization**: Added `deanonymize_text` to `TickerAnonymizer` and patched `cli/main.py` to reverse-map "ASSET_XXX" to real company names in the final report, effectively resolving "[Company Name]" placeholders for the user while keeping the internal system blind.
|
||||||
- **Alpaca Integration**: Added `tradingagents/dataflows/alpaca.py` to support `get_stock_data` via Alpaca Data API v2. Registered as a vendor option in `interface.py` and `default_config.py`. Requires `ALPACA_API_KEY` and `ALPACA_API_SECRET` in `.env`.
|
- **Alpaca Integration**: Added `tradingagents/dataflows/alpaca.py` to support `get_stock_data` via Alpaca Data API v2. Registered as a vendor option in `interface.py` and `default_config.py`. Requires `ALPACA_API_KEY` and `ALPACA_API_SECRET` in `.env`.
|
||||||
|
- **CRITICAL FIX: Memory Leak**: Implemented `FinancialSituationMemory.clear()` and `TradingAgentsGraph.reset_memory()` to wipe agent context between runs. This prevents hallucinations from bleeding across days in long simulations.
|
||||||
|
- **CRITICAL FIX: Blind Logs**: Updated `_log_state` to explicitly capture `market_regime` and `regime_metrics`, ensuring we can audit decision logic relative to market conditions.
|
||||||
|
- **CRITICAL FIX: Crash Prevention**: Added guard logic in `propagate()` to handle "Dead State" (Rejected Trades) gracefully, preventing crashes when `process_signal` tries to read non-existent buy prices.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,14 @@ class FinancialSituationMemory:
|
||||||
return matched_results
|
return matched_results
|
||||||
|
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
"""Clear the memory by deleting and recreating the collection."""
|
||||||
|
try:
|
||||||
|
self.chroma_client.delete_collection(self.situation_collection.name)
|
||||||
|
self.situation_collection = self.chroma_client.create_collection(name=self.situation_collection.name)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to clear memory {self.situation_collection.name}: {e}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Example usage
|
# Example usage
|
||||||
matcher = FinancialSituationMemory()
|
matcher = FinancialSituationMemory()
|
||||||
|
|
|
||||||
|
|
@ -165,8 +165,18 @@ class TradingAgentsGraph:
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def reset_memory(self):
|
||||||
|
"""Clear all agent memories to prevent context bleeding between runs."""
|
||||||
|
self.bull_memory.clear()
|
||||||
|
self.bear_memory.clear()
|
||||||
|
self.trader_memory.clear()
|
||||||
|
self.invest_judge_memory.clear()
|
||||||
|
self.risk_manager_memory.clear()
|
||||||
|
|
||||||
def propagate(self, company_name, trade_date):
|
def propagate(self, company_name, trade_date):
|
||||||
"""Run the trading agents graph for a company on a specific date."""
|
"""Run the trading agents graph for a company on a specific date."""
|
||||||
|
# 1. FIX MEMORY LEAK
|
||||||
|
self.reset_memory()
|
||||||
|
|
||||||
self.ticker = company_name
|
self.ticker = company_name
|
||||||
|
|
||||||
|
|
@ -197,14 +207,30 @@ class TradingAgentsGraph:
|
||||||
# Log state
|
# Log state
|
||||||
self._log_state(trade_date, final_state)
|
self._log_state(trade_date, final_state)
|
||||||
|
|
||||||
# Return decision and processed signal
|
# 3. FIX CRASH RISK: Handle Dead State gracefully
|
||||||
return final_state, self.process_signal(final_state["final_trade_decision"])
|
trade_decision = final_state["final_trade_decision"]
|
||||||
|
|
||||||
|
# If trade was rejected by a Gate (Fact Check or Risk), return raw decision
|
||||||
|
if trade_decision.get("action") == "HOLD" and "REJECTED" in trade_decision.get("reasoning", ""):
|
||||||
|
processed_signal = {
|
||||||
|
"action": "HOLD",
|
||||||
|
"quantity": 0,
|
||||||
|
"reason": trade_decision["reasoning"]
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# Only process if it's a valid attempt
|
||||||
|
processed_signal = self.process_signal(trade_decision)
|
||||||
|
|
||||||
|
return final_state, processed_signal
|
||||||
|
|
||||||
def _log_state(self, trade_date, final_state):
|
def _log_state(self, trade_date, final_state):
|
||||||
"""Log the final state to a JSON file."""
|
"""Log the final state to a JSON file."""
|
||||||
self.log_states_dict[str(trade_date)] = {
|
self.log_states_dict[str(trade_date)] = {
|
||||||
"company_of_interest": final_state["company_of_interest"],
|
"company_of_interest": final_state["company_of_interest"],
|
||||||
"trade_date": final_state["trade_date"],
|
"trade_date": final_state["trade_date"],
|
||||||
|
# 2. FIX BLIND SPOT: Log the Math
|
||||||
|
"market_regime": final_state.get("market_regime", "UNKNOWN"),
|
||||||
|
"regime_metrics": final_state.get("regime_metrics", {}),
|
||||||
"market_report": final_state["market_report"],
|
"market_report": final_state["market_report"],
|
||||||
"sentiment_report": final_state["sentiment_report"],
|
"sentiment_report": final_state["sentiment_report"],
|
||||||
"news_report": final_state["news_report"],
|
"news_report": final_state["news_report"],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue