You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.3 KiB

package service
import (
"context"
"fmt"
"strings"
"time"
"market-data-service/api"
"market-data-service/internal/repository"
)
// StockServiceImpl 股票服务实现
type StockServiceImpl struct {
repo *repository.StockRepository
config *DataSourceConfig
}
// DataSourceConfig 数据源配置
type DataSourceConfig struct {
Adapter interface{}
}
// NewStockService 创建股票服务
func NewStockService(repo *repository.StockRepository) StockService {
return &StockServiceImpl{
repo: repo,
}
}
// QueryKLines 查询K线数据
func (s *StockServiceImpl) QueryKLines(ctx context.Context, req *api.KLineQueryRequest) (*api.KLineData, error) {
// 解析日期
start, err := time.Parse("20060102", req.Start)
if err != nil {
return nil, fmt.Errorf("invalid start date: %w", err)
}
end, err := time.Parse("20060102", req.End)
if err != nil {
return nil, fmt.Errorf("invalid end date: %w", err)
}
end = end.Add(24 * time.Hour).Add(-time.Second) // 包含结束日期全天
// 获取K线数据
items, err := s.repo.GetKLines(ctx, req.Symbol, req.Freq, start, end, req.Adjust)
if err != nil {
return nil, err
}
// 处理复权
if req.Adjust != api.AdjustNone {
items = s.applyAdjust(ctx, req.Symbol, items, req.Adjust)
}
return &api.KLineData{
Symbol: req.Symbol,
Freq: req.Freq,
Adjust: req.Adjust,
Count: len(items),
Items: items,
}, nil
}
// applyAdjust 应用复权
func (s *StockServiceImpl) applyAdjust(ctx context.Context, symbol string, items []api.KLineItem, adjustType api.AdjustType) []api.KLineItem {
// TODO: 实现复权计算
// 1. 从数据库获取复权系数
// 2. 根据前复权/后复权计算价格
return items
}
// ListSymbols 查询标的列表
func (s *StockServiceImpl) ListSymbols(ctx context.Context, req *api.SymbolListRequest) (*api.SymbolListData, error) {
symbols, total, err := s.repo.ListSymbols(ctx, req)
if err != nil {
return nil, err
}
return &api.SymbolListData{
Total: total,
Page: req.Page,
Size: req.Size,
Items: symbols,
}, nil
}
// BatchQueryKLines 批量查询K线
func (s *StockServiceImpl) BatchQueryKLines(ctx context.Context, req *api.BatchKLineRequest) (*api.BatchKLineData, error) {
results := make([]api.BatchKLineResult, len(req.Symbols))
for i, symbol := range req.Symbols {
singleReq := &api.KLineQueryRequest{
Symbol: symbol,
Start: req.Start,
End: req.End,
Freq: req.Freq,
Adjust: req.Adjust,
}
data, err := s.QueryKLines(ctx, singleReq)
results[i] = api.BatchKLineResult{
Symbol: symbol,
Success: err == nil,
}
if err != nil {
results[i].Error = err.Error()
} else {
results[i].Data = &api.KLineSubData{
Count: data.Count,
Items: data.Items,
}
}
}
return &api.BatchKLineData{Results: results}, nil
}
// GetTradingDates 获取交易日历
func (s *StockServiceImpl) GetTradingDates(ctx context.Context, req *api.TradingDatesRequest) (*api.TradingDatesData, error) {
return s.repo.GetTradingDates(ctx, req.Start, req.End)
}
// SyncSymbolsFromSource 从数据源同步标的列表
func (s *StockServiceImpl) SyncSymbolsFromSource(ctx context.Context, adapter interface{ FetchSymbols(assetType string) ([]struct {
SymbolID string
Name string
Exchange string
}, error) }) error {
// TODO: 实现从Tushare同步标的列表
return nil
}