diff --git a/README.md b/README.md index 5f22c26..abde94b 100644 --- a/README.md +++ b/README.md @@ -148,3 +148,12 @@ page design: - 参数遍历回测 对目标目标k线时序段前的k线进行特征提取, 再进行回测评估, 反复迭代得到Alpha + +- CodeMirror web端代码编辑器 +- go plugin 恶意代码: + - IO操作(限制 import 路径, 只允许导入 sig-pub 下的包), + - 死循环(1.编译时注入timeout cancel机制, 2.编译为单独进程os.Exit) +- 目标人群: + - programmer: git repository actions, golang python js..., code examples + - trader: ai strategy coder (交易员, 交易策略, 交易信号, 交易执行) + - 新手学习者: 引导, 普通用户(player) ai strategy coder diff --git a/config/exchange.toml b/config/exchange.toml index caa8ef0..19bb205 100644 --- a/config/exchange.toml +++ b/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 diff --git a/pkg/indicator/ema.go b/pkg/indicator/ema.go index 01acc08..893d88c 100644 --- a/pkg/indicator/ema.go +++ b/pkg/indicator/ema.go @@ -13,6 +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线序列类型"}, }, } } @@ -24,15 +25,17 @@ func (c *EMA) CandlePeriods(ctx IIndicatorContext) int16 { // Calculate 计算单根k线sma指标 func (c *EMA) Calculate(ctx IIndicatorContext) (vector float64) { window := ctx.Input().Int16("window") + pt := ctx.Input().PriceType() + prevEma, ok := ctx.State().Get("_vector", 1) if !ok { // 初始值用 sma 替代 - prevEma = ctx.Series(1, window).Close().Avg() + prevEma = ctx.Series(1, window).Price(pt).Avg() } multiplier := 2.0 / float64(window+1) - close := ctx.Get(0).CloseF64() - vector = multiplier*close + (1-multiplier)*prevEma + price := ctx.Get(0).Price(pt) + vector = multiplier*price + (1-multiplier)*prevEma // same: vector = ((close - prevEma) * multiplier) + prevEma ctx.State().Set("_vector", vector) diff --git a/pkg/types/input.go b/pkg/types/input.go index f136a9b..dbe2495 100644 --- a/pkg/types/input.go +++ b/pkg/types/input.go @@ -94,6 +94,11 @@ 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 + } + } v, err := cast.ToStringE(in.get(k, "string")) if err != nil { panic(fmt.Errorf("input string parse error: %s", k)) @@ -109,6 +114,15 @@ func (in Input) Time(k string) (v time.Time) { return } +func (in Input) PriceType(k ...string) (v KPriceType) { + key := "pt" + if len(k) > 0 { + key = k[0] + } + v = KPriceType(in.String(key)) + return +} + func (in Input) Decode(k string, point any) { t := fmt.Sprintf("%T", point) v := in.get(k, t) @@ -143,6 +157,7 @@ const ( InputTypeInt InputTypeUInt InputTypeTime + InputTypeKPriceType InputTypeUFloats // float数组 InputTypeUFloats2D // float二维数组 InputTypeSelect // 单选 @@ -154,6 +169,7 @@ type InputArg struct { Desc string `json:"desc"` Type InputType `json:"type"` // 参数类型 Options []InputOption `json:"options"` // 单选/多选选项列表 + Default any `json:"default"` // 默认值 TODO 构造context前将默认值置入input } type InputOption struct { diff --git a/pkg/types/kline.go b/pkg/types/kline.go index a4729fc..15d40fd 100644 --- a/pkg/types/kline.go +++ b/pkg/types/kline.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "sig-pub/api/pb" "sig-pub/pkg/types/decimals" @@ -88,6 +89,37 @@ func (k Kline) HL2() float64 { return (k.HighF64() + k.LowF64()) / 2 } +func (s Kline) Price(t KPriceType) float64 { + switch t { + case KPriceTypeOpen: + return s.OpenF64() + case KPriceTypeClose: + return s.CloseF64() + case KPriceTypeHigh: + return s.HighF64() + case KPriceTypeLow: + return s.LowF64() + case KPriceTypeVol: + return s.VolF64() + case KPriceTypeVolQuote: + return s.VolQtyF64() + default: + panic(fmt.Errorf("kline price type %s not support", t)) + } +} + +type KPriceType string + +const ( + KPriceTypeHigh KPriceType = "high" + KPriceTypeLow KPriceType = "low" + KPriceTypeOpen KPriceType = "open" + KPriceTypeClose KPriceType = "close" + KPriceTypeVol KPriceType = "vol" + KPriceTypeVolQuote KPriceType = "volQuote" + KPriceTypeDefault KPriceType = KPriceTypeClose +) + // ChannelKline k线订阅消息 type ChannelKline struct { ExgInstId string `json:"instId"` // 交易所交易产品id,如 BTC_USDT_SWAP diff --git a/pkg/types/kline_series.go b/pkg/types/kline_series.go index 407dd7d..505143d 100644 --- a/pkg/types/kline_series.go +++ b/pkg/types/kline_series.go @@ -153,6 +153,25 @@ 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 { + switch t { + case KPriceTypeHigh: + return s.High() + case KPriceTypeLow: + return s.Low() + case KPriceTypeOpen: + return s.Open() + case KPriceTypeClose: + return s.Close() + case KPriceTypeVol: + return s.Vol() + case KPriceTypeVolQuote: + return s.VolQuote() + default: + panic(fmt.Errorf("unsupport kline price type: %s", t)) + } +} + // InstanceIntervalKlineSeries 保存各币种各周期k线 type InstanceIntervalKlineSeries struct { scopeIntervals []Interval