add money flow

This commit is contained in:
yanweidong
2026-02-12 19:41:52 +08:00
parent 2918eee808
commit 6d60bd5a61
4 changed files with 201 additions and 0 deletions

21
cmd/money/main.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import (
"git.apinb.com/dataset/stock/internal/config"
"git.apinb.com/dataset/stock/internal/impl"
"git.apinb.com/dataset/stock/internal/logic/a"
)
var (
ServiceKey = "stock"
)
func main() {
// 配置初始化
config.New(ServiceKey)
// 创建实现层
impl.NewImpl()
a.NewApiClient()
a.GetTushareMoneyFlow()
}

View File

@@ -0,0 +1,133 @@
package a
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/dataset/stock/internal/impl"
"git.apinb.com/dataset/stock/internal/models"
)
// 请求结构根据Tushare API格式定义
type TushareReq struct {
APIName string `json:"api_name"`
Token string `json:"token"`
Params MParams `json:"params"`
Fields []string `json:"fields"`
}
type MParams map[string]interface{}
// 响应结构
type TushareResp struct {
RequestID string `json:"request_id"`
Code int `json:"code"`
Data struct {
Fields []string `json:"fields"`
Items [][]any `json:"items"`
HasMore bool `json:"has_more"`
Count int `json:"count"`
} `json:"data"`
Msg string `json:"msg"`
}
// 资金流数据模型
type Moneyflow struct {
TsCode string `json:"ts_code"` // 股票代码
TradeDate string `json:"trade_date"` // 交易日期
BuySmAmount float64 `json:"buy_sm_amount"` // 小单买入
BuyMdAmount float64 `json:"buy_md_amount"` // 中单买入
BuyLgAmount float64 `json:"buy_lg_amount"` // 大单买入
BuyElgAmount float64 `json:"buy_elg_amount"` // 超大单买入
// 可根据需要补充净流入字段
NetMfAmount float64 `json:"net_mf_amount"` // 净流入额(万元)
}
func GetTushareMoneyFlow() {
dates := GetTradeDateBy(3, true)
allData := make(map[string][]Moneyflow)
for _, date := range dates {
list, _ := fetchMoneyFlowByDate(TushareToken, date)
for _, mf := range list {
allData[mf.TsCode] = append(allData[mf.TsCode], mf)
}
}
for code, dailyList := range allData {
if len(dailyList) < 3 {
continue
}
// 判断资金流向是否正在正增长。
isGrenter := false
if dailyList[2].NetMfAmount > dailyList[1].NetMfAmount && dailyList[1].NetMfAmount > dailyList[0].NetMfAmount {
isGrenter = true
}
data := models.MoneyTotal{
Code: code,
Last1DayMfAmount: dailyList[2].NetMfAmount,
Last1DayTotalAmount: dailyList[2].BuySmAmount + dailyList[2].BuyMdAmount + dailyList[2].BuyLgAmount + dailyList[2].BuyElgAmount,
IsGreaterPervious: isGrenter,
}
for _, item := range dailyList {
data.Last3DayMfAmount += item.NetMfAmount
data.Last3DayTotalAmount += item.BuySmAmount + item.BuyMdAmount + item.BuyLgAmount + item.BuyElgAmount
}
data.Last1DayMfAmount = utils.FloatRound(data.Last1DayMfAmount, 2)
data.Last1DayTotalAmount = utils.FloatRound(data.Last1DayTotalAmount, 2)
data.Last3DayMfAmount = utils.FloatRound(data.Last3DayMfAmount, 2)
data.Last3DayTotalAmount = utils.FloatRound(data.Last3DayTotalAmount, 2)
var cnt int64
impl.DBService.Model(&models.MoneyTotal{}).Where("code=?", code).Count(&cnt)
if cnt == 0 {
impl.DBService.Create(&data)
} else {
impl.DBService.Model(&models.MoneyTotal{}).Where("code=?", code).Updates(&data)
}
}
}
// 1. 获取指定日期所有股票的资金流向
func fetchMoneyFlowByDate(token, date string) ([]Moneyflow, error) {
url := "http://api.tushare.pro"
payload := TushareReq{
APIName: "moneyflow",
Token: token,
Params: MParams{"trade_date": date},
Fields: []string{"ts_code", "trade_date", "buy_sm_amount", "buy_md_amount", "buy_lg_amount", "buy_elg_amount", "net_mf_amount"},
}
reqBytes, _ := json.Marshal(payload)
resp, err := http.Post(url, "application/json", strings.NewReader(string(reqBytes)))
if err != nil {
return nil, fmt.Errorf("#100 %v", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var tushareResp TushareResp
if err := json.Unmarshal(body, &tushareResp); err != nil {
fmt.Println(string(body))
return nil, fmt.Errorf("#101 %v", err)
}
// 解析二维数组
var result []Moneyflow
for _, item := range tushareResp.Data.Items {
// 此处简化了类型转换生产环境需严格处理err
mf := Moneyflow{
TsCode: item[0].(string),
TradeDate: item[1].(string),
BuySmAmount: item[2].(float64),
BuyMdAmount: item[3].(float64),
BuyLgAmount: item[4].(float64),
BuyElgAmount: item[5].(float64),
NetMfAmount: item[6].(float64),
}
result = append(result, mf)
}
return result, nil
}

View File

@@ -16,6 +16,30 @@ func NewApiClient() {
TushareClient = tushare.New(TushareToken)
}
// 获取最近N个交易日,asc=true 顺序asc=false 倒序
func GetTradeDateBy(max int, asc bool) []string {
reply, _ := TushareClient.TradeCal(map[string]string{
"is_open": "1",
"end_date": time.Now().Format("20060102"),
}, []string{"exchange", "cal_date"})
var days []string
for i := 0; i < max; i++ {
days = append(days, reply.Data.Items[i][1].(string))
}
// 将days的数据倒序
if asc {
var newDays []string
for i := len(days) - 1; i >= 0; i-- {
newDays = append(newDays, days[i])
}
return newDays
}
return days
}
func ReturnLastDay() (string, string) {
now := time.Now()
end := now.Format("20060102")

View File

@@ -0,0 +1,23 @@
package models
import "git.apinb.com/bsm-sdk/core/database"
// 资金流数据模型
type MoneyTotal struct {
ID uint `gorm:"primarykey"`
Code string // 股票代码
Last1DayMfAmount float64 // 最近1天净流入额万元
Last3DayMfAmount float64 // 最近3天净流入额万元
Last1DayTotalAmount float64 // 最近1天中大单总流入额万元
Last3DayTotalAmount float64 // 最近3天中大单总流入额万元
IsGreaterPervious bool // 是否比上一日大单流入额多
}
func init() {
database.AppendMigrate(&MoneyTotal{})
}
// TableName 设置表名
func (MoneyTotal) TableName() string {
return "money_total"
}