138 lines
3.3 KiB
Go
138 lines
3.3 KiB
Go
package ent
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/banbox/banbot/biz"
|
|
"github.com/banbox/banbot/btime"
|
|
"github.com/banbox/banbot/config"
|
|
"github.com/banbox/banbot/core"
|
|
"github.com/banbox/banbot/opt"
|
|
"github.com/banbox/banbot/orm"
|
|
"github.com/banbox/banbot/orm/ormo"
|
|
utils2 "github.com/banbox/banexg/utils"
|
|
"strconv"
|
|
)
|
|
|
|
func hisSharpe(args []string) error {
|
|
var configPaths config.ArrString
|
|
var inPath string
|
|
var sub = flag.NewFlagSet("fac", flag.ExitOnError)
|
|
sub.Var(&configPaths, "config", "config path to use, Multiple -config options may be used")
|
|
sub.StringVar(&inPath, "in", "", "path for all pairs orders e.g.: orders.gob")
|
|
err_ := sub.Parse(args)
|
|
if err_ != nil {
|
|
return err_
|
|
}
|
|
core.SetRunMode(core.RunModeBackTest)
|
|
err := biz.SetupComsExg(&config.CmdArgs{
|
|
Configs: configPaths,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var startMs = config.TimeRange.StartMS
|
|
var endMS = config.TimeRange.EndMS
|
|
if len(config.StakeCurrency) == 0 {
|
|
return errors.New("`stake_currency` in yml is required")
|
|
}
|
|
var tfSecs int
|
|
var orders []*ormo.InOutOrder
|
|
if inPath == "" {
|
|
return errors.New("-in is required")
|
|
} else {
|
|
inPath = config.ParsePath(inPath)
|
|
}
|
|
orders, err = ormo.LoadOrdersGob(inPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var exsMap = make(map[int32]*orm.ExSymbol)
|
|
var pairMap = make(map[string]int32)
|
|
var totalCost float64
|
|
var validOdNum int
|
|
if len(orders) > 0 {
|
|
startMs = orders[0].RealEnterMS()
|
|
endMS = orders[0].RealExitMS()
|
|
for _, od := range orders {
|
|
curStart := od.RealEnterMS()
|
|
if curStart < startMs && curStart > 0 {
|
|
startMs = curStart
|
|
}
|
|
curEnd := od.RealExitMS()
|
|
if curEnd > endMS {
|
|
endMS = curEnd
|
|
}
|
|
tfSecs = max(tfSecs, utils2.TFToSecs(od.Timeframe))
|
|
curCost := od.EnterCost()
|
|
if curCost > 0 {
|
|
totalCost += curCost
|
|
validOdNum += 1
|
|
}
|
|
if _, ok := pairMap[od.Symbol]; !ok {
|
|
exs, err := orm.GetExSymbolCur(od.Symbol)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
exsMap[exs.ID] = exs
|
|
pairMap[od.Symbol] = exs.ID
|
|
}
|
|
}
|
|
} else {
|
|
return errors.New("orders is empty")
|
|
}
|
|
if validOdNum == 0 {
|
|
return errors.New("no valid orders")
|
|
}
|
|
if tfSecs == 0 {
|
|
tfSecs = utils2.TFToSecs("1d")
|
|
}
|
|
tf := "1d"
|
|
// 滚动测试因子
|
|
rangeStart, _ := btime.ParseTimeMS("2022-11-19")
|
|
rangeEnd, _ := btime.ParseTimeMS("2024-11-18")
|
|
pairOrders, err := opt.CutOrdersInRange(orders, rangeStart, rangeEnd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pairOrders = map[string][]*ormo.InOutOrder{
|
|
"WIF/USDT:USDT": pairOrders["WIF/USDT:USDT"],
|
|
}
|
|
pairInfos, err := opt.CalcPairStats(pairOrders, rangeStart, rangeEnd, tf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
initFund := config.WalletAmounts["USDT"]
|
|
rangeSecs := (rangeEnd - rangeStart) / 1000
|
|
for _, sta := range pairInfos {
|
|
reals := make([]float64, 0, len(sta.Returns))
|
|
curFund := initFund
|
|
for _, v := range sta.Returns {
|
|
curFund += v
|
|
reals = append(reals, curFund)
|
|
}
|
|
sharp, _, err := opt.CalcMeasuresByReal(reals, rangeSecs, "", 0, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
labels := make([]string, len(reals))
|
|
for i := range reals {
|
|
labels[i] = strconv.Itoa(i)
|
|
}
|
|
g := opt.Chart{
|
|
Labels: labels,
|
|
Datasets: []*opt.ChartDs{
|
|
{
|
|
Label: "pow(x, 1.5)",
|
|
Data: reals,
|
|
BorderColor: "rgb(75, 192, 192)",
|
|
},
|
|
},
|
|
}
|
|
g.DumpFile("D:/dump_pairs2.html")
|
|
fmt.Printf("%s sharpe: %v", sta.Symbol, sharp)
|
|
}
|
|
return nil
|
|
}
|