Import 9 alphaear finance skills
- alphaear-deepear-lite: DeepEar Lite API integration - alphaear-logic-visualizer: Draw.io XML finance diagrams - alphaear-news: Real-time finance news (10+ sources) - alphaear-predictor: Kronos time-series forecasting - alphaear-reporter: Professional financial reports - alphaear-search: Web search + local RAG - alphaear-sentiment: FinBERT/LLM sentiment analysis - alphaear-signal-tracker: Signal evolution tracking - alphaear-stock: A-Share/HK/US stock data Updates: - All scripts updated to use universal .env path - Added JINA_API_KEY, LLM_*, DEEPSEEK_API_KEY to .env.example - Updated load_dotenv() to use ~/.config/opencode/.env
This commit is contained in:
76
skills/alphaear-predictor/scripts/forecast_agent.py
Normal file
76
skills/alphaear-predictor/scripts/forecast_agent.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import json
|
||||
from typing import List, Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
from loguru import logger
|
||||
import pandas as pd
|
||||
|
||||
from .kronos_predictor import KronosPredictorUtility
|
||||
from .utils.database_manager import DatabaseManager
|
||||
from .schema.models import ForecastResult, KLinePoint, InvestmentSignal
|
||||
|
||||
class ForecastUtils:
|
||||
"""
|
||||
预测辅助工具 (ForecastUtils)
|
||||
提供数据准备、基础模型预测等功能。
|
||||
LLM 调整逻辑已移交 Agent 执行 (参考 scripts/prompts/PROMPTS.md)。
|
||||
"""
|
||||
|
||||
def __init__(self, db: DatabaseManager):
|
||||
self.db = db
|
||||
self.predictor_util = KronosPredictorUtility() # Singleton
|
||||
|
||||
def get_base_forecast(
|
||||
self,
|
||||
ticker: str,
|
||||
signals: List[Dict] = None,
|
||||
lookback: int = 20,
|
||||
pred_len: int = 5,
|
||||
) -> Optional[List[KLinePoint]]:
|
||||
"""
|
||||
获取基础预测数据 (技术面 + 新闻模型定量修正)。
|
||||
Agent 应随后使用 PROMPTS.md 中的指令进行定性调整。
|
||||
"""
|
||||
logger.info(f"🔮 Generating base forecast for {ticker}...")
|
||||
|
||||
# 1. 获取历史数据
|
||||
from .stock_tools import StockTools
|
||||
stock_tools = StockTools(self.db, auto_update=False)
|
||||
|
||||
end_date = datetime.now().strftime("%Y-%m-%d")
|
||||
# 宽放一点时间以确保有足够的交易日
|
||||
start_date = (datetime.now() - pd.Timedelta(days=max(lookback * 4, 90))).strftime("%Y-%m-%d")
|
||||
df = stock_tools.get_stock_price(ticker, start_date=start_date, end_date=end_date)
|
||||
|
||||
if df.empty or len(df) < lookback:
|
||||
# Try force sync
|
||||
df = stock_tools.get_stock_price(ticker, start_date=start_date, end_date=end_date, force_sync=True)
|
||||
|
||||
if df.empty:
|
||||
logger.warning(f"⚠️ No history data for {ticker}")
|
||||
return None
|
||||
|
||||
effective_lookback = lookback
|
||||
if len(df) < lookback:
|
||||
if len(df) < 10:
|
||||
logger.warning(f"⚠️ Insufficient history for {ticker}")
|
||||
return None
|
||||
effective_lookback = len(df)
|
||||
|
||||
# 2. 准备信号上下文
|
||||
signal_lines = []
|
||||
for s in (signals or []):
|
||||
try:
|
||||
title = s.get('title', '') if isinstance(s, dict) else getattr(s, 'title', '')
|
||||
summary = s.get('summary', '') if isinstance(s, dict) else getattr(s, 'summary', '')
|
||||
if title or summary:
|
||||
signal_lines.append(f"- {title}: {summary}")
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
signals_context = "\n".join(signal_lines).strip()
|
||||
|
||||
# 3. 模型预测 (News-Adjusted if context exists)
|
||||
if signals_context:
|
||||
return self.predictor_util.get_base_forecast(df, lookback=effective_lookback, pred_len=pred_len, news_text=signals_context)
|
||||
else:
|
||||
return self.predictor_util.get_base_forecast(df, lookback=effective_lookback, pred_len=pred_len, news_text=None)
|
||||
Reference in New Issue
Block a user