package ent import ( "fmt" "github.com/banbox/banbot/btime" "github.com/banbox/banbot/config" "github.com/banbox/banbot/core" "github.com/banbox/banbot/exg" "github.com/banbox/banbot/orm" utils2 "github.com/banbox/banbot/utils" "github.com/banbox/banexg" "github.com/banbox/banexg/errs" "github.com/banbox/banexg/utils" "github.com/banbox/banstagy/com" "math" "path/filepath" "sort" "strconv" ) /* 永续合约资金费率结算后一段时间,如果资金费率<-0.0035,未来5分钟有较大概率下降 */ type FRate struct { Time int64 Data []*com.CodeVal } func runFundEnter() *errs.Error { exgId := "binance" exchange, err := exg.GetWith(exgId, banexg.MarketLinear, banexg.MarketSwap) if err != nil { return err } _, err = orm.LoadMarkets(exchange, false) if err != nil { return err } dumpDir := filepath.Join(config.GetDataDir(), "dump") err_ := utils2.EnsureDir(dumpDir, 0755) if err_ != nil { return errs.New(errs.CodeIOWriteFail, err_) } dumpPath := filepath.Join(dumpDir, exgId+"_fundingRate.json") his := make(map[string]map[int64]float64) err_ = utils.ReadJsonFile(dumpPath, &his, utils.JsonNumDefault) if err_ != nil { return errs.New(errs.CodeIOReadFail, err_) } dates := make(map[int64]*FRate) for code, timeMap := range his { for dateMS, val := range timeMap { sta, ok := dates[dateMS] if !ok { sta = &FRate{Time: dateMS} dates[dateMS] = sta } sta.Data = append(sta.Data, &com.CodeVal{ Code: code, Val: val, }) } } arr := make([]*FRate, 0, len(dates)) for _, it := range dates { arr = append(arr, it) } sort.Slice(arr, func(i, j int) bool { return arr[i].Time < arr[j].Time }) // 按时间戳,对资金费率绝对值较大的,筛选K线并记录价格 rows := make([][]string, 0) barNum := 20 backOff := 5 head := []string{"time", "code", "rate", "price"} for i := 0; i < barNum; i++ { sid := i - backOff if sid >= 0 { sid += 1 } head = append(head, "p"+strconv.Itoa(sid)) } rows = append(rows, head) for _, dt := range arr { sort.Slice(dt.Data, func(i, j int) bool { return math.Abs(dt.Data[i].Val) > math.Abs(dt.Data[j].Val) }) startMS := dt.Time - int64(backOff)*60000 for _, it := range dt.Data { if math.Abs(it.Val) < 0.0005 { break } exs, err := orm.GetExSymbol(exchange, it.Code) if err != nil { return err } _, bars, err := orm.GetOHLCV(exs, "1m", startMS, 0, barNum, false) if err != nil { return err } if len(bars) < barNum { continue } row := make([]string, 0, 4+barNum) initPrice := bars[backOff].Open row = append(row, btime.ToDateStr(dt.Time, core.DefaultDateFmt), it.Code, strconv.FormatFloat(it.Val, 'f', 6, 64), fmt.Sprintf("%.4e", initPrice)) var pct float64 for i, b := range bars { if i < backOff { pct = (1 - b.Open/initPrice) * 100 } else { pct = (b.Close/initPrice - 1) * 100 } row = append(row, strconv.FormatFloat(pct, 'f', 4, 64)) } rows = append(rows, row) } } outPath := filepath.Join(dumpDir, exgId+"_fr.csv") return utils2.WriteCsvFile(outPath, rows, false) }