// fetch 是数据拉取验证命令(CLI): // // go run ./cmd/fetch # 拉取全量可转债实时行情 // go run ./cmd/fetch -code 113667 # 拉取指定可转债历史K线 package main import ( "context" "flag" "fmt" "os" "sort" "stock-analysis/internal/datasource/eastmoney" "stock-analysis/internal/datasource/fallback" "stock-analysis/internal/datasource/tencent" "stock-analysis/internal/service" ) func main() { code := flag.String("code", "", "可转债代码(如 113667),指定时拉取历史K线") days := flag.Int("days", 30, "打印最近N根K线") flag.Parse() ds := fallback.New(eastmoney.NewClient(), tencent.NewClient()) svc := service.NewMarketService(ds) ctx := context.Background() if *code != "" { if err := fetchKline(ctx, svc, *code, *days); err != nil { fmt.Fprintln(os.Stderr, "kline error:", err) os.Exit(1) } return } if err := fetchConvertibles(ctx, svc); err != nil { fmt.Fprintln(os.Stderr, "list error:", err) os.Exit(1) } } // fetchConvertibles 拉取并打印全量可转债。 func fetchConvertibles(ctx context.Context, svc *service.MarketService) error { bonds, err := svc.ListConvertibles(ctx) if err != nil { return err } fmt.Printf("共拉取可转债 %d 只\n\n", len(bonds)) // 按溢价率升序展示前 15 只(低溢价候选池雏形)。 sort.Slice(bonds, func(i, j int) bool { return bonds[i].PremiumRate < bonds[j].PremiumRate }) fmt.Printf("%-8s %-10s %8s %7s %8s %8s %8s %8s %8s\n", "代码", "名称", "价格", "涨跌%", "溢价率%", "转股价值", "转股价", "纯债价值", "正股") for i, b := range bonds { if i >= 15 { break } fmt.Printf("%-8s %-10s %8.3f %7.2f %8.2f %8.2f %8.2f %8.2f %s\n", b.Code, b.Name, b.Price, b.ChangePct, b.PremiumRate, b.ConvertValue, b.ConvertPrice, b.PureBondVal, b.StockName) } fmt.Println("\n... (仅展示前15只,按溢价率升序)") return nil } // fetchKline 拉取并打印指定可转债的历史K线。 func fetchKline(ctx context.Context, svc *service.MarketService, code string, days int) error { klines, err := svc.GetDailyKline(ctx, code, "20200101") if err != nil { return err } fmt.Printf("代码 %s 共 %d 根日K(%s ~ %s)\n\n", code, len(klines), klines[0].Date, klines[len(klines)-1].Date) start := len(klines) - days if start < 0 { start = 0 } fmt.Printf("%-12s %8s %8s %8s %8s %12s\n", "日期", "开盘", "收盘", "最高", "最低", "成交量") for _, k := range klines[start:] { fmt.Printf("%-12s %8.3f %8.3f %8.3f %8.3f %12d\n", k.Date, k.Open, k.Close, k.High, k.Low, k.Volume) } return nil }