simple_trend.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """
  2. 简化趋势策略 - 追求高收益
  3. 核心逻辑:
  4. 1. Summer生态 + 价格>MA20 + 趋势向上 = 满仓
  5. 2. 其他情况 = 空仓
  6. 3. 硬止损-10%,追踪止损-15%
  7. """
  8. from typing import Dict, Any, Optional
  9. import pandas as pd
  10. import numpy as np
  11. from datetime import datetime
  12. from agents.base import AgentBase, AgentSignal, SignalDirection, SignalStrength
  13. from core.ecosystem import MacroRegime, UnifiedEcosystem
  14. class SimpleTrendAgent(AgentBase):
  15. """
  16. 简化趋势策略
  17. 规则:
  18. - Summer/Spring生态 + 收盘价>MA20 + MA5>MA20 = 满仓做多
  19. - 其他情况 = 空仓
  20. """
  21. def __init__(self):
  22. super().__init__(
  23. name="simple_trend",
  24. max_position=1.0,
  25. min_confidence=0.5
  26. )
  27. self.ma_fast = 5
  28. self.ma_slow = 20
  29. self.stop_loss_pct = 0.10
  30. self.trailing_stop_pct = 0.15
  31. def generate_signal(
  32. self,
  33. price_data: pd.DataFrame,
  34. ecosystem: Optional[UnifiedEcosystem] = None
  35. ) -> Optional[AgentSignal]:
  36. """生成交易信号"""
  37. if len(price_data) < self.ma_slow + 5:
  38. return None
  39. close = price_data['close']
  40. ma_fast = close.rolling(self.ma_fast).mean().iloc[-1]
  41. ma_slow = close.rolling(self.ma_slow).mean().iloc[-1]
  42. current_price = close.iloc[-1]
  43. # 计算趋势强度
  44. trend_strength = (ma_fast - ma_slow) / ma_slow
  45. # 确定方向
  46. if ecosystem and ecosystem.macro.regime in [MacroRegime.SUMMER, MacroRegime.SPRING]:
  47. if current_price > ma_slow and ma_fast > ma_slow and trend_strength > 0.005:
  48. # 强做多信号
  49. direction = SignalDirection.LONG
  50. confidence = min(1.0, 0.6 + trend_strength * 10)
  51. position_size = 1.0 # 满仓
  52. elif current_price < ma_slow * 0.95:
  53. # 跌破支撑,平仓
  54. direction = SignalDirection.NEUTRAL
  55. confidence = 0.5
  56. position_size = 0.0
  57. else:
  58. return None
  59. else:
  60. # 非 Summer/Spring,观望
  61. direction = SignalDirection.NEUTRAL
  62. confidence = 0.5
  63. position_size = 0.0
  64. # 根据中观健康度调整
  65. if ecosystem and direction == SignalDirection.LONG:
  66. health = ecosystem.meso.health_score / 100
  67. position_size *= health
  68. confidence *= health
  69. if direction == SignalDirection.NEUTRAL and position_size == 0:
  70. return AgentSignal(
  71. agent_name=self.name,
  72. direction=direction,
  73. strength=SignalStrength.WEAK,
  74. confidence=confidence,
  75. suggested_position=0.0,
  76. expected_return=0.0,
  77. win_probability=0.5,
  78. timestamp=datetime.now(),
  79. valid_until=datetime.now(),
  80. metadata={"reason": "outside_preferred_regime_or_no_trend"}
  81. )
  82. return AgentSignal(
  83. agent_name=self.name,
  84. direction=direction,
  85. strength=SignalStrength.STRONG if confidence > 0.7 else SignalStrength.MEDIUM,
  86. confidence=confidence,
  87. suggested_position=position_size,
  88. expected_return=0.25, # 预期25%年化
  89. win_probability=0.6,
  90. timestamp=datetime.now(),
  91. valid_until=datetime.now(),
  92. metadata={
  93. "price": current_price,
  94. "ma_fast": ma_fast,
  95. "ma_slow": ma_slow,
  96. "trend_strength": trend_strength,
  97. "regime": ecosystem.macro.regime.value if ecosystem else "unknown"
  98. }
  99. )
  100. def get_expected_return(self, price_data: pd.DataFrame, ecosystem=None) -> float:
  101. return 0.25
  102. def get_win_probability(self, price_data: pd.DataFrame, ecosystem=None) -> float:
  103. return 0.6