From 796a5d25817de5f4c46260c11f09cb59ddd86912 Mon Sep 17 00:00:00 2001 From: strange Date: Fri, 5 Dec 2025 18:38:36 +0800 Subject: [PATCH] 1 --- README.md | 9 ++++++- pkg/indicator/indicator.go | 10 ++++++++ pkg/strategy/gold_x.go | 1 + pkg/utils/rands/weight_choice.go | 37 +++++++++++++++++++++++++++ pkg/utils/rands/weight_choice_test.go | 24 +++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 pkg/utils/rands/weight_choice.go create mode 100644 pkg/utils/rands/weight_choice_test.go diff --git a/README.md b/README.md index b2922b0..822716c 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,8 @@ kline时间窗口 Dragonfly redis替换 -CCXT – [加密货币交易所交易库](https://github.com/ccxt/ccxt) +CCXT – [加密货币交易所交易接口库](https://github.com/ccxt/ccxt) +[binance交易接口库](https://pkg.go.dev/github.com/adshao/go-binance) ### 绘图框架 tradingview advanced-charts: @@ -114,3 +115,9 @@ macd dif/dea -> state -> plot - 量化交易 - web3: - 智能合约 solidity NTF + +generate(metaTradePlan[sig,risk,trade,close params]) + -> tradePlan + -> backtest + -> result + -> statistics diff --git a/pkg/indicator/indicator.go b/pkg/indicator/indicator.go index 44e0299..ad56cb3 100644 --- a/pkg/indicator/indicator.go +++ b/pkg/indicator/indicator.go @@ -58,3 +58,13 @@ type IIndicatorState interface { // Series 获取指标之前存储的状态序列 offset >= 1, count >= 1 Series(k string, offset, count int16) (v series.Floats, ok bool) } + +// 单个指标参数校验 +type IIndicatorValidator interface { + InputValidator(input types.Input) error +} + +// 策略中多个组合指标参数校验 -> strategy(ind1, ind2) +type IStrategyValidator interface { + InputValidator(input types.Input) error +} diff --git a/pkg/strategy/gold_x.go b/pkg/strategy/gold_x.go index b62c9a4..1adc42e 100644 --- a/pkg/strategy/gold_x.go +++ b/pkg/strategy/gold_x.go @@ -36,6 +36,7 @@ func (s *GoldX) CandlePeriods(ctx ISingleSigStrategyContext) int16 { ) } +// $MACD > 0 && #crossover($MACD.dea, $MACD.dif) -> long func (s *GoldX) Update(ctx ISingleSigStrategyContext) (side types.Side) { macd := ctx.Indicator("MACD", ctx.Input()) diff --git a/pkg/utils/rands/weight_choice.go b/pkg/utils/rands/weight_choice.go new file mode 100644 index 0000000..d0c18ad --- /dev/null +++ b/pkg/utils/rands/weight_choice.go @@ -0,0 +1,37 @@ +package rands + +import ( + "math/rand/v2" + "time" +) + +var ( + rad = rand.New(rand.NewPCG(uint64(time.Now().Unix()), uint64(time.Now().UnixNano()))) +) + +// Choice 一个选项包含一个泛型项以及一个权重,该权重用于控制其被选中的频率 +type Choice[W int | int32 | int64, T any] struct { + Weight W + Item T +} + +// WeightedChoice 加权随机选择, 从所提供的选项中返回一个选项, 权重值为 0 的选项永远不会被选中 +// Based on this algorithm: http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ +func WeightedChoice[W int | int32 | int64, T any](choices []Choice[W, T], rd ...*rand.Rand) (ret Choice[W, T], ok bool) { + sum := int64(0) + for _, c := range choices { + sum += int64(c.Weight) + } + crd := rad + if len(rd) > 0 && rd[0] != nil { + crd = rd[0] + } + r := crd.Int64N(sum) + for _, c := range choices { + r -= int64(c.Weight) + if r < 0 { + return c, true + } + } + return +} diff --git a/pkg/utils/rands/weight_choice_test.go b/pkg/utils/rands/weight_choice_test.go new file mode 100644 index 0000000..7a4feec --- /dev/null +++ b/pkg/utils/rands/weight_choice_test.go @@ -0,0 +1,24 @@ +package rands + +import ( + "fmt" + "testing" +) + +func TestWeightedChoice(t *testing.T) { + choices := []Choice[int, int]{ + {Weight: 10, Item: 300}, + {Weight: 1, Item: 100}, + {Weight: 5, Item: 200}, + } + times := make(map[int]int) + for range 100000 { + c, ok := WeightedChoice(choices) + if !ok { + t.Error("weight choice error") + return + } + times[c.Item]++ + } + fmt.Println(times) // map[100:6156 200:31280 300:62564] +}