collector.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. """
  2. 一级信号采集器
  3. 采集所有原始信号并标准化为[-1, 1]区间
  4. """
  5. from dataclasses import dataclass, field
  6. from typing import Dict, List, Optional, Any
  7. from datetime import datetime
  8. import pandas as pd
  9. import numpy as np
  10. @dataclass
  11. class PrimarySignal:
  12. """一级信号数据结构"""
  13. source: str # 信号来源
  14. signal_type: str # 信号类型
  15. value: float # 信号值 (-1 to 1)
  16. raw_value: float # 原始值
  17. timestamp: datetime
  18. metadata: Dict[str, Any] = field(default_factory=dict)
  19. class SignalCollector:
  20. """
  21. 信号采集器
  22. 从各模块采集一级信号:
  23. - 趋势质量评分
  24. - 卡尔曼滤波趋势
  25. - RSRS阻力支撑强度
  26. - HMM状态概率
  27. - 生态识别结果
  28. """
  29. def __init__(self):
  30. self.signal_history: List[PrimarySignal] = []
  31. def collect_from_ecosystem(self, ecosystem: Any) -> List[PrimarySignal]:
  32. """从生态识别模块采集信号"""
  33. signals = []
  34. # 宏观生态信号
  35. if hasattr(ecosystem, 'macro'):
  36. macro_signal = self._encode_macro_regime(ecosystem.macro)
  37. signals.append(PrimarySignal(
  38. source="ecosystem",
  39. signal_type="macro_regime",
  40. value=macro_signal,
  41. raw_value=ecosystem.macro.regime.value,
  42. timestamp=datetime.now(),
  43. metadata={"confidence": ecosystem.macro.confidence}
  44. ))
  45. # 中观健康度信号
  46. if hasattr(ecosystem, 'meso'):
  47. health_signal = (ecosystem.meso.health_score - 50) / 50 # 标准化到-1,1
  48. signals.append(PrimarySignal(
  49. source="ecosystem",
  50. signal_type="health_score",
  51. value=health_signal,
  52. raw_value=ecosystem.meso.health_score,
  53. timestamp=datetime.now(),
  54. metadata={"level": ecosystem.meso.health_level.value}
  55. ))
  56. # 微观状态信号
  57. if hasattr(ecosystem, 'micro'):
  58. micro_signal = self._encode_micro_state(ecosystem.micro)
  59. signals.append(PrimarySignal(
  60. source="ecosystem",
  61. signal_type="micro_state",
  62. value=micro_signal,
  63. raw_value=ecosystem.micro.state.value,
  64. timestamp=datetime.now()
  65. ))
  66. return signals
  67. def collect_from_indicators(
  68. self,
  69. price_data: pd.DataFrame,
  70. trend_quality_score: Optional[float] = None,
  71. kalman_trend: Optional[float] = None,
  72. rsrs_score: Optional[float] = None
  73. ) -> List[PrimarySignal]:
  74. """从技术指标采集信号"""
  75. signals = []
  76. # 趋势质量信号
  77. if trend_quality_score is not None:
  78. signals.append(PrimarySignal(
  79. source="indicator",
  80. signal_type="trend_quality",
  81. value=(trend_quality_score - 50) / 50,
  82. raw_value=trend_quality_score,
  83. timestamp=datetime.now()
  84. ))
  85. # 卡尔曼趋势信号
  86. if kalman_trend is not None:
  87. signals.append(PrimarySignal(
  88. source="indicator",
  89. signal_type="kalman_trend",
  90. value=np.clip(kalman_trend * 100, -1, 1),
  91. raw_value=kalman_trend,
  92. timestamp=datetime.now()
  93. ))
  94. # RSRS信号
  95. if rsrs_score is not None:
  96. signals.append(PrimarySignal(
  97. source="indicator",
  98. signal_type="rsrs",
  99. value=(rsrs_score - 0.5) * 2, # 0-1 映射到 -1,1
  100. raw_value=rsrs_score,
  101. timestamp=datetime.now()
  102. ))
  103. # MACD信号
  104. macd_signal = self._calculate_macd_signal(price_data)
  105. if macd_signal is not None:
  106. signals.append(PrimarySignal(
  107. source="indicator",
  108. signal_type="macd",
  109. value=macd_signal,
  110. raw_value=macd_signal,
  111. timestamp=datetime.now()
  112. ))
  113. return signals
  114. def collect_from_agents(self, agent_signals: Dict[str, Any]) -> List[PrimarySignal]:
  115. """从智能体采集信号"""
  116. signals = []
  117. for agent_name, signal in agent_signals.items():
  118. if signal is None:
  119. continue
  120. # 转换方向为数值
  121. direction_value = {
  122. "long": 1.0,
  123. "short": -1.0,
  124. "neutral": 0.0
  125. }.get(signal.direction.value, 0.0)
  126. signals.append(PrimarySignal(
  127. source=f"agent_{agent_name}",
  128. signal_type="agent_direction",
  129. value=direction_value * signal.confidence,
  130. raw_value=direction_value,
  131. timestamp=datetime.now(),
  132. metadata={
  133. "confidence": signal.confidence,
  134. "strength": signal.strength.value if hasattr(signal, 'strength') else "medium"
  135. }
  136. ))
  137. return signals
  138. def _encode_macro_regime(self, macro: Any) -> float:
  139. """编码宏观生态为数值信号"""
  140. regime_map = {
  141. "spring": 0.5,
  142. "summer": 1.0,
  143. "autumn": -0.5,
  144. "winter": -1.0,
  145. "unknown": 0.0
  146. }
  147. return regime_map.get(macro.regime.value, 0.0)
  148. def _encode_micro_state(self, micro: Any) -> float:
  149. """编码微观状态为数值信号"""
  150. state_map = {
  151. "trending": 1.0,
  152. "ranging": 0.0,
  153. "reversing": -1.0
  154. }
  155. return state_map.get(micro.state.value, 0.0)
  156. def _calculate_macd_signal(self, data: pd.DataFrame) -> Optional[float]:
  157. """计算MACD信号"""
  158. if len(data) < 35:
  159. return None
  160. exp1 = data['close'].ewm(span=12, adjust=False).mean()
  161. exp2 = data['close'].ewm(span=26, adjust=False).mean()
  162. macd = exp1 - exp2
  163. signal = macd.ewm(span=9, adjust=False).mean()
  164. # 标准化
  165. histogram = macd - signal
  166. return np.clip(histogram.iloc[-1] / data['close'].iloc[-1] * 100, -1, 1)
  167. def get_collected_signals(self) -> List[PrimarySignal]:
  168. """获取所有采集的信号"""
  169. return self.signal_history