strange 7 months ago
parent
commit
27b3ff8af1
  1. 1
      api/trading.proto
  2. 4
      config/exchange.toml
  3. 1
      internal/trading/trading_service.go
  4. 16
      pkg/indicator/boll.go
  5. 2
      pkg/indicator/ema.go
  6. 2
      pkg/indicator/indicator_registry.go
  7. 8
      pkg/indicator/sam.go
  8. 16
      pkg/types/input.go
  9. 30
      pkg/types/kline.go
  10. 14
      pkg/types/kline_series.go

1
api/trading.proto

@ -78,6 +78,7 @@ message RspStrategySeries {
repeated int32 signal = 1; // pub.Side: 1.buy,2.sell repeated int32 signal = 1; // pub.Side: 1.buy,2.sell
repeated int64 times = 2; repeated int64 times = 2;
repeated double prices = 3; repeated double prices = 3;
repeated int32 direction = 4; // 1.up,2.down
} }
message ReqBacktest { message ReqBacktest {

4
config/exchange.toml

@ -19,8 +19,8 @@ marketSubscribeLimit = 16
consumeBatch = 1024 consumeBatch = 1024
consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume
# httpProxy = "" # httpProxy = ""
# httpProxy = "http://192.168.1.5:7890" httpProxy = "http://192.168.1.5:7890"
httpProxy = "http://10.255.183.209:7890" # httpProxy = "http://10.255.183.209:7890"
# 模拟盘API交易地址如下: # 模拟盘API交易地址如下:
# REST:https://www.okx.com # REST:https://www.okx.com

1
internal/trading/trading_service.go

@ -360,6 +360,7 @@ func (svc *TradingService) StrategySeries(ctx context.Context, req *pb.ReqStrate
} }
side := lang.Ternary(sigSide == types.SideLong, pb.Side_BUY, pb.Side_SELL) side := lang.Ternary(sigSide == types.SideLong, pb.Side_BUY, pb.Side_SELL)
rsp.Signal = append(rsp.Signal, int32(side)) rsp.Signal = append(rsp.Signal, int32(side))
rsp.Direction = append(rsp.Direction, lang.Ternary[int32](k.OpenF64() > k.CloseF64(), 1, 2))
rsp.Prices = append(rsp.Prices, k.CloseF64()) rsp.Prices = append(rsp.Prices, k.CloseF64())
// 处理k线时间 // 处理k线时间
ktime := k.Ts ktime := k.Ts

16
pkg/indicator/boll.go

@ -5,20 +5,20 @@ import (
"sig-pub/pkg/types" "sig-pub/pkg/types"
) )
// Boll 布林带 // BOLL 布林带
type Boll struct { type BOLL struct {
} }
func (c *Boll) Meta() IndicatorMeta { func (c *BOLL) Meta() IndicatorMeta {
return IndicatorMeta{ return IndicatorMeta{
Name: "Boll", Name: "BOLL",
Input: []types.InputArg{ Input: []types.InputArg{
{Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"}, {Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"},
{Name: "pt", Type: types.InputTypeKPriceType, Desc: "k线序列类型"}, {Name: "pt", Type: types.InputTypePriceType, Desc: "k线序列类型"},
}, },
State: []string{"ub", "lb"}, State: []string{"ub", "lb"},
Plots: []Plot{ Plots: []Plot{
{Name: "中轨", State: "vector", Type: PlotHistogram, Props: PlotProps{"color": ColorOrange}}, {Name: "中轨", State: "vector", Type: PlotLine, Props: PlotProps{"color": ColorOrange}},
{Name: "上轨", State: "ub", Type: PlotLine, Props: PlotProps{"color": ColorRed2}}, {Name: "上轨", State: "ub", Type: PlotLine, Props: PlotProps{"color": ColorRed2}},
{Name: "下轨", State: "lb", Type: PlotLine, Props: PlotProps{"color": ColorRed2}}, {Name: "下轨", State: "lb", Type: PlotLine, Props: PlotProps{"color": ColorRed2}},
{Name: "布林带阴影", State: "ub,lb", Type: PlotShadow, Props: PlotProps{"shadowColor": "rgba(241, 169, 166, 0.2)"}}, {Name: "布林带阴影", State: "ub,lb", Type: PlotShadow, Props: PlotProps{"shadowColor": "rgba(241, 169, 166, 0.2)"}},
@ -26,11 +26,11 @@ func (c *Boll) Meta() IndicatorMeta {
} }
} }
func (c *Boll) CandlePeriods(ctx IIndicatorContext) int16 { func (c *BOLL) CandlePeriods(ctx IIndicatorContext) int16 {
return ctx.Input().Int16("window") return ctx.Input().Int16("window")
} }
func (c *Boll) Calculate(ctx IIndicatorContext) (vector float64) { func (c *BOLL) Calculate(ctx IIndicatorContext) (vector float64) {
window := ctx.Input().Int16("window") window := ctx.Input().Int16("window")
pt := ctx.Input().PriceType() pt := ctx.Input().PriceType()
priceSeries := ctx.Series(0, int16(window)).Price(pt) priceSeries := ctx.Series(0, int16(window)).Price(pt)

2
pkg/indicator/ema.go

@ -13,7 +13,7 @@ func (c *EMA) Meta() IndicatorMeta {
Name: "EMA", Name: "EMA",
Input: []types.InputArg{ Input: []types.InputArg{
{Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"}, {Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"},
{Name: "pt", Type: types.InputTypeKPriceType, Desc: "k线序列类型"}, {Name: "pt", Type: types.InputTypePriceType, Desc: "k线序列类型"},
}, },
} }
} }

2
pkg/indicator/indicator_registry.go

@ -25,7 +25,7 @@ func (r *IndicatorRegistry) Init() (err error) {
r.MustRegistIndicator(&MACD{}) r.MustRegistIndicator(&MACD{})
r.MustRegistIndicator(&OBV{}) r.MustRegistIndicator(&OBV{})
r.MustRegistIndicator(&WOBV{}) r.MustRegistIndicator(&WOBV{})
r.MustRegistIndicator(&Boll{}) r.MustRegistIndicator(&BOLL{})
r.MustRegistIndicator(&SuperTrend{}) r.MustRegistIndicator(&SuperTrend{})
r.MustRegistIndicator(&ADX{}) r.MustRegistIndicator(&ADX{})
r.MustRegistIndicator(&KDJ{}) r.MustRegistIndicator(&KDJ{})

8
pkg/indicator/sam.go

@ -14,7 +14,8 @@ func (c *SMA) Meta() IndicatorMeta {
return IndicatorMeta{ return IndicatorMeta{
Name: "SMA", Name: "SMA",
Input: []types.InputArg{ Input: []types.InputArg{
{Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"}, {Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小", Default: 9},
{Name: "pt", Type: types.InputTypePriceType, Desc: "k线序列类型", Default: types.PriceTypeDefault},
}, },
} }
} }
@ -26,9 +27,10 @@ func (c *SMA) CandlePeriods(ctx IIndicatorContext) int16 {
// Calculate 计算单根k线sma指标 // Calculate 计算单根k线sma指标
func (c *SMA) Calculate(ctx IIndicatorContext) (vector float64) { func (c *SMA) Calculate(ctx IIndicatorContext) (vector float64) {
window := ctx.Input().Int16("window") window := ctx.Input().Int16("window")
closeSeries := ctx.Series(0, window).Close() pt := ctx.Input().PriceType()
priceSeries := ctx.Series(0, window).Price(pt)
// sma := talib.Sma(closeSeries, int(window)) // sma := talib.Sma(closeSeries, int(window))
// _ = sma[len(sma)-1] // _ = sma[len(sma)-1]
vector = closeSeries.Avg() vector = priceSeries.Avg()
return return
} }

16
pkg/types/input.go

@ -97,7 +97,7 @@ func (in Input) Int16(k string) (v int16) {
func (in Input) String(k string) (v string) { func (in Input) String(k string) (v string) {
if k == "pt" && in != nil { if k == "pt" && in != nil {
if _, ok := in[k]; !ok { if _, ok := in[k]; !ok {
in[k] = KPriceTypeDefault in[k] = PriceTypeDefault
} }
} }
v, err := cast.ToStringE(in.get(k, "string")) v, err := cast.ToStringE(in.get(k, "string"))
@ -115,12 +115,12 @@ func (in Input) Time(k string) (v time.Time) {
return return
} }
func (in Input) PriceType(k ...string) (v KPriceType) { func (in Input) PriceType(k ...string) (v PriceType) {
key := "pt" key := "pt"
if len(k) > 0 { if len(k) > 0 {
key = k[0] key = k[0]
} }
v = KPriceType(in.String(key)) v = PriceType(in.String(key))
return return
} }
@ -158,11 +158,11 @@ const (
InputTypeInt InputTypeInt
InputTypeUInt InputTypeUInt
InputTypeTime InputTypeTime
InputTypeKPriceType // K线价格类型 InputTypePriceType // K线价格类型
InputTypeUFloats // float数组 InputTypeUFloats // float数组
InputTypeUFloats2D // float二维数组 InputTypeUFloats2D // float二维数组
InputTypeSelect // 单选 InputTypeSelect // 单选
InputTypeCheckBox // 多选 InputTypeCheckBox // 多选
) )
type InputArg struct { type InputArg struct {

30
pkg/types/kline.go

@ -89,35 +89,35 @@ func (k Kline) HL2() float64 {
return (k.HighF64() + k.LowF64()) / 2 return (k.HighF64() + k.LowF64()) / 2
} }
func (s Kline) Price(t KPriceType) float64 { func (s Kline) Price(t PriceType) float64 {
switch t { switch t {
case KPriceTypeOpen: case PriceTypeOpen:
return s.OpenF64() return s.OpenF64()
case KPriceTypeClose: case PriceTypeClose:
return s.CloseF64() return s.CloseF64()
case KPriceTypeHigh: case PriceTypeHigh:
return s.HighF64() return s.HighF64()
case KPriceTypeLow: case PriceTypeLow:
return s.LowF64() return s.LowF64()
case KPriceTypeVol: case PriceTypeVol:
return s.VolF64() return s.VolF64()
case KPriceTypeVolQuote: case PriceTypeVolQuote:
return s.VolQtyF64() return s.VolQtyF64()
default: default:
panic(fmt.Errorf("kline price type %s not support", t)) panic(fmt.Errorf("kline price type %s not support", t))
} }
} }
type KPriceType string type PriceType string
const ( const (
KPriceTypeHigh KPriceType = "high" PriceTypeHigh PriceType = "high"
KPriceTypeLow KPriceType = "low" PriceTypeLow PriceType = "low"
KPriceTypeOpen KPriceType = "open" PriceTypeOpen PriceType = "open"
KPriceTypeClose KPriceType = "close" PriceTypeClose PriceType = "close"
KPriceTypeVol KPriceType = "vol" PriceTypeVol PriceType = "vol"
KPriceTypeVolQuote KPriceType = "volQuote" PriceTypeVolQuote PriceType = "volQuote"
KPriceTypeDefault KPriceType = KPriceTypeClose PriceTypeDefault PriceType = PriceTypeClose
) )
// ChannelKline k线订阅消息 // ChannelKline k线订阅消息

14
pkg/types/kline_series.go

@ -153,19 +153,19 @@ func (s Klines) VolQuote() series.Floats {
return collect.Mapping(s, func(k Kline) float64 { return decimals.MustToFloat64(k.VolQuote) }) return collect.Mapping(s, func(k Kline) float64 { return decimals.MustToFloat64(k.VolQuote) })
} }
func (s Klines) Price(t KPriceType) series.Floats { func (s Klines) Price(t PriceType) series.Floats {
switch t { switch t {
case KPriceTypeHigh: case PriceTypeHigh:
return s.High() return s.High()
case KPriceTypeLow: case PriceTypeLow:
return s.Low() return s.Low()
case KPriceTypeOpen: case PriceTypeOpen:
return s.Open() return s.Open()
case KPriceTypeClose: case PriceTypeClose:
return s.Close() return s.Close()
case KPriceTypeVol: case PriceTypeVol:
return s.Vol() return s.Vol()
case KPriceTypeVolQuote: case PriceTypeVolQuote:
return s.VolQuote() return s.VolQuote()
default: default:
panic(fmt.Errorf("unsupport kline price type: %s", t)) panic(fmt.Errorf("unsupport kline price type: %s", t))

Loading…
Cancel
Save