mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-14 08:16:56 +08:00
feat(config): 增加新闻源配置与数据库迁移支持
- 在config.json.example中添加新闻源相关配置示例,支持telegram频道订阅 - 扩展数据库表结构,新增traders表多字段支持信号源和杠杆参数 - 新增NewsConfig结构体及相关telegram新闻配置数据模型 - 在交易决策上下文结构Context中添加新闻数据news字段支持传递新闻 - 在交易决策构建用户提示信息时加入相关新闻内容 - 优化数据库操作代码,支持交易所和交易员配置的完整字段读取与更新 - 添加数据库exchanges表迁移逻辑,重建表结构和触发器以支持新字段 - 引入第三方库github.com/samber/lo用于集合操作 - 在go.mod添加新的依赖模块,并更新相关依赖版本
This commit is contained in:
145
news/provider/default/default.go
Normal file
145
news/provider/default/default.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package news
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nofx/news"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultNewsProvider 默认新闻提供者实现(参考示例)
|
||||
// 展示如何实现 NewsProvider 接口
|
||||
type DefaultNewsProvider struct {
|
||||
// API配置(根据实际数据源调整)
|
||||
APIKey string
|
||||
BaseURL string
|
||||
Timeout time.Duration
|
||||
CacheTime time.Duration
|
||||
|
||||
// 可选:缓存机制
|
||||
cache map[string]cacheEntry
|
||||
}
|
||||
|
||||
type cacheEntry struct {
|
||||
news []news.NewsItem
|
||||
timestamp time.Time
|
||||
}
|
||||
|
||||
// NewDefaultNewsProvider 创建默认新闻提供者
|
||||
func NewDefaultNewsProvider(apiKey, baseURL string) *DefaultNewsProvider {
|
||||
return &DefaultNewsProvider{
|
||||
APIKey: apiKey,
|
||||
BaseURL: baseURL,
|
||||
Timeout: 30 * time.Second,
|
||||
CacheTime: 5 * time.Minute, // 5分钟缓存
|
||||
cache: make(map[string]cacheEntry),
|
||||
}
|
||||
}
|
||||
|
||||
// FetchNews 实现 NewsProvider 接口
|
||||
// 按币种批量获取最新新闻,返回值按symbol分组
|
||||
func (p *DefaultNewsProvider) FetchNews(symbols []string, limit int) (map[string][]news.NewsItem, error) {
|
||||
if len(symbols) == 0 {
|
||||
return make(map[string][]news.NewsItem), nil
|
||||
}
|
||||
|
||||
result := make(map[string][]news.NewsItem)
|
||||
|
||||
for _, symbol := range symbols {
|
||||
// 1. 检查缓存
|
||||
if cached, ok := p.getFromCache(symbol); ok {
|
||||
result[symbol] = cached
|
||||
continue
|
||||
}
|
||||
|
||||
// 2. 从数据源获取(具体实现留空,由你后续补充)
|
||||
news, err := p.fetchFromSource(symbol, limit)
|
||||
if err != nil {
|
||||
// 单个币种失败不影响其他币种
|
||||
continue
|
||||
}
|
||||
|
||||
// 3. 更新缓存
|
||||
p.updateCache(symbol, news)
|
||||
result[symbol] = news
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getFromCache 从缓存获取新闻
|
||||
func (p *DefaultNewsProvider) getFromCache(symbol string) ([]news.NewsItem, bool) {
|
||||
entry, exists := p.cache[symbol]
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// 检查缓存是否过期
|
||||
if time.Since(entry.timestamp) > p.CacheTime {
|
||||
delete(p.cache, symbol)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return entry.news, true
|
||||
}
|
||||
|
||||
// updateCache 更新缓存
|
||||
func (p *DefaultNewsProvider) updateCache(symbol string, news []news.NewsItem) {
|
||||
p.cache[symbol] = cacheEntry{
|
||||
news: news,
|
||||
timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// fetchFromSource 从数据源获取新闻(具体实现由你补充)
|
||||
func (p *DefaultNewsProvider) fetchFromSource(symbol string, limit int) ([]news.NewsItem, error) {
|
||||
// TODO: 实现具体的新闻获取逻辑
|
||||
// 可选的数据源:
|
||||
// 1. CryptoPanic API: https://cryptopanic.com/developers/api/
|
||||
// 2. CoinGecko Events API
|
||||
// 3. 交易所公告(币安、OKX等)
|
||||
// 4. Twitter/X API
|
||||
// 5. Reddit API
|
||||
// 6. 自定义爬虫
|
||||
|
||||
// 示例返回结构(实际需要调用API)
|
||||
news := []news.NewsItem{
|
||||
{
|
||||
Symbol: symbol,
|
||||
Headline: fmt.Sprintf("%s 相关新闻标题", symbol),
|
||||
Source: "CryptoPanic", // 或其他来源
|
||||
URL: "https://example.com/news/123",
|
||||
PublishedAt: time.Now().Add(-1 * time.Hour),
|
||||
Sentiment: 0, // -100 到 100
|
||||
Impact: 50, // 0 到 100
|
||||
Summary: "新闻摘要内容...",
|
||||
Tags: []string{"breaking", "market"},
|
||||
},
|
||||
}
|
||||
|
||||
return news, nil
|
||||
}
|
||||
|
||||
// 可选:实现其他辅助方法
|
||||
|
||||
// FilterByImpact 按影响力过滤新闻
|
||||
func (p *DefaultNewsProvider) FilterByImpact(items []news.NewsItem, minImpact int) []news.NewsItem {
|
||||
filtered := make([]news.NewsItem, 0)
|
||||
for _, item := range items {
|
||||
if item.Impact >= minImpact {
|
||||
filtered = append(filtered, item)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// FilterByTime 按时间过滤新闻(只保留最近N小时的)
|
||||
func (p *DefaultNewsProvider) FilterByTime(items []news.NewsItem, hours int) []news.NewsItem {
|
||||
cutoff := time.Now().Add(-time.Duration(hours) * time.Hour)
|
||||
filtered := make([]news.NewsItem, 0)
|
||||
for _, item := range items {
|
||||
if item.PublishedAt.After(cutoff) {
|
||||
filtered = append(filtered, item)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
Reference in New Issue
Block a user