23 changed files with 410 additions and 212 deletions
@ -1,21 +1,68 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/url" |
||||
"sig-pub/internal/gateway" |
||||
"sig-pub/pkg/config" |
||||
"sig-pub/pkg/grpc/discovery" |
||||
"sig-pub/pkg/grpc/generic" |
||||
"sig-pub/pkg/utils/exit" |
||||
|
||||
"github.com/hashicorp/consul/api" |
||||
_ "github.com/mostynb/go-grpc-compression/snappy" // 注册grpc snappy compress
|
||||
"google.golang.org/grpc" |
||||
"google.golang.org/grpc/credentials/insecure" |
||||
) |
||||
|
||||
type GateConf struct { |
||||
HttpAddr string |
||||
WsAddr string |
||||
HttpAddr string |
||||
WsAddr string |
||||
SigServer string |
||||
} |
||||
|
||||
// http 网关
|
||||
func main() { |
||||
gateConf := config.MustLoadConfig(new(GateConf), "config/gate.toml") |
||||
server := gateway.Route() |
||||
err := server.Run(gateConf.HttpAddr) |
||||
// load config
|
||||
conf := config.MustLoadConfig(new(config.Configuration), "config/config.toml") |
||||
gateConf := config.MustLoadConfig(new(GateConf), "config/gateway.toml") |
||||
|
||||
// consul 配置
|
||||
cc := api.DefaultConfig() |
||||
cc.Address = conf.Consul.Address |
||||
client, err := api.NewClient(cc) |
||||
if err != nil { |
||||
panic(fmt.Errorf("consul client error: %v", err)) |
||||
} |
||||
|
||||
// consul service discovery
|
||||
dis := discovery.NewConsulDiscovery(client) |
||||
resolver := dis.Resolver() |
||||
gpcGenericClientFactory := generic.NewGpcGenericClientFactory( |
||||
discovery.ConsulSchema, |
||||
grpc.WithTransportCredentials(insecure.NewCredentials()), |
||||
grpc.WithResolvers(resolver), |
||||
) |
||||
if err := gpcGenericClientFactory.Init(); err != nil { |
||||
panic(err) |
||||
} |
||||
if err := dis.WatchServices(gpcGenericClientFactory.RefreshService); err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
sigServerUrl, err := url.Parse(gateConf.SigServer) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
gateServer := gateway.NewGateServer(sigServerUrl, gpcGenericClientFactory) |
||||
if err := gateServer.Init(); err != nil { |
||||
panic(err) |
||||
} |
||||
go func() { |
||||
if err := gateServer.Run(gateConf.HttpAddr); err != nil { |
||||
panic(err) |
||||
} |
||||
}() |
||||
|
||||
exit.Await() |
||||
} |
||||
|
||||
@ -1,54 +1,37 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"sig-pub/internal/sig" |
||||
"sig-pub/pkg/config" |
||||
"sig-pub/pkg/grpc/discovery" |
||||
"sig-pub/pkg/grpc/generic" |
||||
"sig-pub/pkg/storage/persist" |
||||
"sig-pub/pkg/utils/exit" |
||||
|
||||
"github.com/hashicorp/consul/api" |
||||
_ "github.com/mostynb/go-grpc-compression/snappy" // 注册grpc snappy compress
|
||||
"google.golang.org/grpc" |
||||
"google.golang.org/grpc/credentials/insecure" |
||||
) |
||||
|
||||
// curl server: /api/sig/backtest/log
|
||||
|
||||
func main() { |
||||
defer exit.Await() |
||||
// load config
|
||||
conf := config.MustLoadConfig(new(config.Configuration), "config/config.toml") |
||||
|
||||
// consul 配置
|
||||
cc := api.DefaultConfig() |
||||
cc.Address = conf.Consul.Address |
||||
client, err := api.NewClient(cc) |
||||
// database
|
||||
db, err := conf.Database.Postgres.NewGormDB() |
||||
if err != nil { |
||||
panic(fmt.Errorf("consul client error: %v", err)) |
||||
} |
||||
|
||||
// consul service discovery
|
||||
dis := discovery.NewConsulDiscovery(client) |
||||
resolver := dis.Resolver() |
||||
gpcGenericClientFactory := generic.NewGpcGenericClientFactory( |
||||
discovery.ConsulSchema, |
||||
grpc.WithTransportCredentials(insecure.NewCredentials()), |
||||
grpc.WithResolvers(resolver), |
||||
) |
||||
if err := gpcGenericClientFactory.Init(); err != nil { |
||||
panic(err) |
||||
} |
||||
if err := dis.WatchServices(gpcGenericClientFactory.RefreshService); err != nil { |
||||
rdb := persist.NewDB(db) |
||||
if err := rdb.Init(); err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
sigServer := sig.NewSigServer(gpcGenericClientFactory) |
||||
if err := sigServer.Init(); err != nil { |
||||
sigServer := sig.NewSigServer(rdb) |
||||
if err = sigServer.Init(); err != nil { |
||||
panic(err) |
||||
} |
||||
go func() { |
||||
if err := sigServer.Run(":7001"); err != nil { |
||||
if err := sigServer.Run(":7009"); err != nil { |
||||
panic(err) |
||||
} |
||||
}() |
||||
|
||||
exit.Await() |
||||
} |
||||
|
||||
@ -0,0 +1,5 @@
|
||||
|
||||
httpAddr = ":7001" |
||||
wsAddr = ":7101" |
||||
|
||||
sigServer = "http://127.0.0.1:7009" # 后台服务 |
||||
@ -0,0 +1,17 @@
|
||||
package repository |
||||
|
||||
import "sig-pub/pkg/storage/persist" |
||||
|
||||
type BacktestRepository struct { |
||||
rdb *persist.DB |
||||
} |
||||
|
||||
func NewBacktestRepository(rdb *persist.DB) *BacktestRepository { |
||||
return &BacktestRepository{ |
||||
rdb: rdb, |
||||
} |
||||
} |
||||
|
||||
func (r *BacktestRepository) ListLog() { |
||||
|
||||
} |
||||
@ -0,0 +1,26 @@
|
||||
package service |
||||
|
||||
import ( |
||||
"net/http" |
||||
repository "sig-pub/internal/sig/repoitory" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
) |
||||
|
||||
type BacktestService struct { |
||||
repo *repository.BacktestRepository |
||||
} |
||||
|
||||
func NewBacktestService(repo *repository.BacktestRepository) *BacktestService { |
||||
return &BacktestService{ |
||||
repo: repo, |
||||
} |
||||
} |
||||
|
||||
func (svc *BacktestService) Route(group *gin.RouterGroup) { |
||||
group.GET("hello", svc.listBacktestLog) |
||||
} |
||||
|
||||
func (svc *BacktestService) listBacktestLog(ctx *gin.Context) { |
||||
ctx.JSON(http.StatusOK, "ojbk") |
||||
} |
||||
@ -0,0 +1,15 @@
|
||||
package service |
||||
|
||||
import ( |
||||
repository "sig-pub/internal/sig/repoitory" |
||||
"sig-pub/pkg/storage/persist" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
) |
||||
|
||||
// Init services list
|
||||
func Init(group *gin.RouterGroup, rdb *persist.DB) { |
||||
backtestRepository := repository.NewBacktestRepository(rdb) |
||||
|
||||
NewBacktestService(backtestRepository).Route(group.Group("/backtest")) |
||||
} |
||||
@ -0,0 +1,73 @@
|
||||
package indicator |
||||
|
||||
import ( |
||||
"sig-pub/pkg/types" |
||||
) |
||||
|
||||
type KDJ struct { |
||||
} |
||||
|
||||
func (c *KDJ) Meta() IndicatorMeta { |
||||
return IndicatorMeta{ |
||||
Name: "KDJ", |
||||
Input: []types.InputArg{ |
||||
{Name: "rsvWindow", Type: types.InputTypeUInt, Desc: "周期"}, // 9
|
||||
{Name: "kWindow", Type: types.InputTypeUInt, Desc: "K平滑"}, // 3
|
||||
{Name: "dWindow", Type: types.InputTypeUInt, Desc: "D平滑"}, // 3
|
||||
}, |
||||
State: []string{"k", "d", "j"}, |
||||
Plots: []Plot{ |
||||
{State: "k", Type: PlotLine, Props: PlotProps{"color": ColorBlue}}, |
||||
{State: "d", Type: PlotLine, Props: PlotProps{"color": ColorYellow}}, |
||||
{State: "j", Type: PlotLine, Props: PlotProps{"color": ColorPurple}}, |
||||
}, |
||||
} |
||||
} |
||||
|
||||
func (c *KDJ) CandlePeriods(ctx IIndicatorContext) int16 { |
||||
return ctx.Input().Int16("rsvWindow") |
||||
} |
||||
|
||||
func (c *KDJ) Calculate(ctx IIndicatorContext) (vector float64) { |
||||
rsvWindow := ctx.Input().Int16("rsvWindow") |
||||
kWindow := float64(ctx.Input().Int16("kWindow")) |
||||
dWindow := float64(ctx.Input().Int16("dWindow")) |
||||
|
||||
klines := ctx.Series(0, rsvWindow) |
||||
if len(klines) < int(rsvWindow) { |
||||
return |
||||
} |
||||
|
||||
closePx := klines[0].CloseF64() |
||||
low := klines.Low().Min() |
||||
high := klines.High().Max() |
||||
|
||||
var rsv float64 |
||||
if high == low { |
||||
rsv = 50 |
||||
} else { |
||||
rsv = (closePx - low) / (high - low) * 100 |
||||
} |
||||
|
||||
// K
|
||||
prevK, ok := ctx.State().Get("k", 1) |
||||
if !ok { |
||||
prevK = 50 |
||||
} |
||||
k := (kWindow-1)/kWindow*prevK + 1/kWindow*rsv |
||||
ctx.State().Set("k", k) |
||||
|
||||
// D
|
||||
prevD, ok := ctx.State().Get("d", 1) |
||||
if !ok { |
||||
prevD = 50 |
||||
} |
||||
d := (dWindow-1)/dWindow*prevD + 1/dWindow*k |
||||
ctx.State().Set("d", d) |
||||
|
||||
// J
|
||||
j := 3*k - 2*d |
||||
ctx.State().Set("j", j) |
||||
|
||||
return j |
||||
} |
||||
Loading…
Reference in new issue