125 lines
3.1 KiB
Go
125 lines
3.1 KiB
Go
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)
|
||
}
|