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 int64 times = 2;
repeated double prices = 3;
repeated int32 direction = 4; // 1.up,2.down
}
message ReqBacktest {

4
config/exchange.toml

@ -19,8 +19,8 @@ marketSubscribeLimit = 16
consumeBatch = 1024
consumeLater = 2000 # 时间到达later或者数据累计到batch触发consume
# httpProxy = ""
# httpProxy = "http://192.168.1.5:7890"
httpProxy = "http://10.255.183.209:7890"
httpProxy = "http://192.168.1.5:7890"
# httpProxy = "http://10.255.183.209:7890"
# 模拟盘API交易地址如下:
# 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)
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())
// 处理k线时间
ktime := k.Ts

16
pkg/indicator/boll.go

@ -5,20 +5,20 @@ import (
"sig-pub/pkg/types"
)
// Boll 布林带
type Boll struct {
// BOLL 布林带
type BOLL struct {
}
func (c *Boll) Meta() IndicatorMeta {
func (c *BOLL) Meta() IndicatorMeta {
return IndicatorMeta{
Name: "Boll",
Name: "BOLL",
Input: []types.InputArg{
{Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小"},
{Name: "pt", Type: types.InputTypeKPriceType, Desc: "k线序列类型"},
{Name: "pt", Type: types.InputTypePriceType, Desc: "k线序列类型"},
},
State: []string{"ub", "lb"},
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: "lb", Type: PlotLine, Props: PlotProps{"color": ColorRed2}},
{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")
}
func (c *Boll) Calculate(ctx IIndicatorContext) (vector float64) {
func (c *BOLL) Calculate(ctx IIndicatorContext) (vector float64) {
window := ctx.Input().Int16("window")
pt := ctx.Input().PriceType()
priceSeries := ctx.Series(0, int16(window)).Price(pt)

2
pkg/indicator/ema.go

@ -13,7 +13,7 @@ func (c *EMA) Meta() IndicatorMeta {
Name: "EMA",
Input: []types.InputArg{
{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(&OBV{})
r.MustRegistIndicator(&WOBV{})
r.MustRegistIndicator(&Boll{})
r.MustRegistIndicator(&BOLL{})
r.MustRegistIndicator(&SuperTrend{})
r.MustRegistIndicator(&ADX{})
r.MustRegistIndicator(&KDJ{})

8
pkg/indicator/sam.go

@ -14,7 +14,8 @@ func (c *SMA) Meta() IndicatorMeta {
return IndicatorMeta{
Name: "SMA",
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指标
func (c *SMA) Calculate(ctx IIndicatorContext) (vector float64) {
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[len(sma)-1]
vector = closeSeries.Avg()
vector = priceSeries.Avg()
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) {
if k == "pt" && in != nil {
if _, ok := in[k]; !ok {
in[k] = KPriceTypeDefault
in[k] = PriceTypeDefault
}
}
v, err := cast.ToStringE(in.get(k, "string"))
@ -115,12 +115,12 @@ func (in Input) Time(k string) (v time.Time) {
return
}
func (in Input) PriceType(k ...string) (v KPriceType) {
func (in Input) PriceType(k ...string) (v PriceType) {
key := "pt"
if len(k) > 0 {
key = k[0]
}
v = KPriceType(in.String(key))
v = PriceType(in.String(key))
return
}
@ -158,11 +158,11 @@ const (
InputTypeInt
InputTypeUInt
InputTypeTime
InputTypeKPriceType // K线价格类型
InputTypeUFloats // float数组
InputTypeUFloats2D // float二维数组
InputTypeSelect // 单选
InputTypeCheckBox // 多选
InputTypePriceType // K线价格类型
InputTypeUFloats // float数组
InputTypeUFloats2D // float二维数组
InputTypeSelect // 单选
InputTypeCheckBox // 多选
)
type InputArg struct {

30
pkg/types/kline.go

@ -89,35 +89,35 @@ func (k Kline) HL2() float64 {
return (k.HighF64() + k.LowF64()) / 2
}
func (s Kline) Price(t KPriceType) float64 {
func (s Kline) Price(t PriceType) float64 {
switch t {
case KPriceTypeOpen:
case PriceTypeOpen:
return s.OpenF64()
case KPriceTypeClose:
case PriceTypeClose:
return s.CloseF64()
case KPriceTypeHigh:
case PriceTypeHigh:
return s.HighF64()
case KPriceTypeLow:
case PriceTypeLow:
return s.LowF64()
case KPriceTypeVol:
case PriceTypeVol:
return s.VolF64()
case KPriceTypeVolQuote:
case PriceTypeVolQuote:
return s.VolQtyF64()
default:
panic(fmt.Errorf("kline price type %s not support", t))
}
}
type KPriceType string
type PriceType string
const (
KPriceTypeHigh KPriceType = "high"
KPriceTypeLow KPriceType = "low"
KPriceTypeOpen KPriceType = "open"
KPriceTypeClose KPriceType = "close"
KPriceTypeVol KPriceType = "vol"
KPriceTypeVolQuote KPriceType = "volQuote"
KPriceTypeDefault KPriceType = KPriceTypeClose
PriceTypeHigh PriceType = "high"
PriceTypeLow PriceType = "low"
PriceTypeOpen PriceType = "open"
PriceTypeClose PriceType = "close"
PriceTypeVol PriceType = "vol"
PriceTypeVolQuote PriceType = "volQuote"
PriceTypeDefault PriceType = PriceTypeClose
)
// 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) })
}
func (s Klines) Price(t KPriceType) series.Floats {
func (s Klines) Price(t PriceType) series.Floats {
switch t {
case KPriceTypeHigh:
case PriceTypeHigh:
return s.High()
case KPriceTypeLow:
case PriceTypeLow:
return s.Low()
case KPriceTypeOpen:
case PriceTypeOpen:
return s.Open()
case KPriceTypeClose:
case PriceTypeClose:
return s.Close()
case KPriceTypeVol:
case PriceTypeVol:
return s.Vol()
case KPriceTypeVolQuote:
case PriceTypeVolQuote:
return s.VolQuote()
default:
panic(fmt.Errorf("unsupport kline price type: %s", t))

Loading…
Cancel
Save