7 changed files with 199 additions and 4 deletions
@ -0,0 +1,30 @@ |
|||||||
|
package sig |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"sig-pub/api/pb" |
||||||
|
"sig-pub/pkg/types" |
||||||
|
"sig-pub/pkg/utils/times" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
func TestKlineSeries(t *testing.T) { |
||||||
|
ks := NewKlineSeries(pb.ExchangeType_SIG, "TEST_USDT", types.Interval5m) |
||||||
|
intervalAdder := types.SupportedIntervals[types.Interval5m] |
||||||
|
KlineBefore0 := int64(1672502400000) |
||||||
|
|
||||||
|
w := times.NewWatch() |
||||||
|
for i := range int64(128000) { |
||||||
|
k := &types.Kline{ |
||||||
|
Ts: intervalAdder(KlineBefore0, i), |
||||||
|
} |
||||||
|
ks.Update(k) |
||||||
|
} |
||||||
|
fmt.Println(w.ElapsedFmt(".")) |
||||||
|
w.Reset() |
||||||
|
for range 100000 { |
||||||
|
a := ks.MustSeries(0, 12) // 500(op/ms)
|
||||||
|
_ = a |
||||||
|
} |
||||||
|
fmt.Println(w.ElapsedFmt(".")) |
||||||
|
} |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
package strategy |
||||||
|
|
||||||
|
import ( |
||||||
|
"sig-pub/pkg/types" |
||||||
|
) |
||||||
|
|
||||||
|
// 多币种多周期策略
|
||||||
|
type MultiInstanceRank struct { |
||||||
|
IIntervalSigStrategy |
||||||
|
rate float64 |
||||||
|
rate2 float64 |
||||||
|
} |
||||||
|
|
||||||
|
func (s *MultiInstanceRank) New() ISigStrategy { |
||||||
|
return &MultiInstanceRank{} |
||||||
|
} |
||||||
|
|
||||||
|
func (s *MultiInstanceRank) Meta() StrategyMeta { |
||||||
|
return StrategyMeta{ |
||||||
|
Name: "MultiInstanceRank", |
||||||
|
Desc: "多币种多周期策略", |
||||||
|
Input: []types.InputArg{ |
||||||
|
{Name: "rate", Type: types.InputTypeUFloat, Desc: "上线影线与基线比例"}, |
||||||
|
{Name: "rate2", Type: types.InputTypeUFloat, Desc: "上线影线之间比例"}, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (s *MultiInstanceRank) Init(input types.Input) (err error) { // 校验参数, 并根据参数初始化策略
|
||||||
|
s.rate = input.Float("rate") |
||||||
|
s.rate2 = input.Float("rate2") |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func (s *MultiInstanceRank) CandlePeriods(ctx IIntervalSigStrategyContext) (insts []string, iss *types.IntervalState[int16]) { |
||||||
|
iss = types.NewIntervalState[int16]() |
||||||
|
iss.Set(types.Interval5m, 1) |
||||||
|
iss.Set(types.Interval15m, 2) |
||||||
|
iss.Set(types.Interval30m, 2) |
||||||
|
return |
||||||
|
} |
||||||
@ -0,0 +1,63 @@ |
|||||||
|
package ta |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"math" |
||||||
|
) |
||||||
|
|
||||||
|
// Pearson 计算皮尔逊相关系数
|
||||||
|
// 1(完美正相关) 0(无线性相关) -1(完美负相关)
|
||||||
|
// |r| 接近 1 表示强相关, 接近 0 表示弱相关
|
||||||
|
// 如果数据近似正态且线性, 适合平稳市场线性走势; 易受极端事件影响
|
||||||
|
func Pearson(series1, series2 []float64) (r float64, err error) { |
||||||
|
length := len(series1) |
||||||
|
if length < 2 || length != len(series2) { |
||||||
|
err = fmt.Errorf("pearson series1 and series2 length not equal") |
||||||
|
return |
||||||
|
} |
||||||
|
avg1 := Avg(series1) |
||||||
|
avg2 := Avg(series2) |
||||||
|
|
||||||
|
var pd_sum, xd_sum, yd_sum float64 |
||||||
|
for i := range length { |
||||||
|
d1 := series1[i] - avg1 |
||||||
|
d2 := series2[i] - avg2 |
||||||
|
xd_sum += d1 * d1 |
||||||
|
yd_sum += d2 * d2 |
||||||
|
pd_sum += d1 * d2 |
||||||
|
} |
||||||
|
r = pd_sum / (math.Sqrt(xd_sum) * math.Sqrt(yd_sum)) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// Spearman 斯皮尔曼相关系数, 针对秩顺序的皮尔逊
|
||||||
|
// 适合波动剧烈市场(如 BTC 牛熊转换);捕捉整体趋势一致性
|
||||||
|
// 在之前的 BTC/ETH/SOL 示例中,Spearman 值略高于 Pearson,表明价格走势有单调一致性,但存在非线性因素(如 SOL 的爆发性增长)。
|
||||||
|
func Spearman(series1, series2 []float64) (r float64, err error) { |
||||||
|
length := len(series1) |
||||||
|
if length < 2 || length != len(series2) { |
||||||
|
err = fmt.Errorf("spearman series1 and series2 length not equal") |
||||||
|
return |
||||||
|
} |
||||||
|
sort1 := make([]float64, length) |
||||||
|
sort2 := make([]float64, length) |
||||||
|
for i := range length { |
||||||
|
sort1[i] = float64(i + 1) |
||||||
|
sort2[i] = float64(i + 1) |
||||||
|
} |
||||||
|
sortFn := func(series []float64, sorts []float64) { |
||||||
|
for i := range series { |
||||||
|
for j := i + 1; j < length; j++ { |
||||||
|
if series[i] > series[j] { |
||||||
|
series[i], series[j] = series[j], series[i] |
||||||
|
sorts[i], sorts[j] = sorts[j], sorts[i] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
sortFn(series1, sort1) |
||||||
|
sortFn(series2, sort2) |
||||||
|
return Pearson(sort1, sort2) |
||||||
|
} |
||||||
|
|
||||||
|
// Kendall 肯德尔相关系数
|
||||||
@ -0,0 +1,16 @@ |
|||||||
|
package ta |
||||||
|
|
||||||
|
func Avg(series []float64) (r float64) { |
||||||
|
length := len(series) |
||||||
|
if length == 0 { |
||||||
|
return |
||||||
|
} |
||||||
|
return Sum(series) / float64(length) |
||||||
|
} |
||||||
|
|
||||||
|
func Sum(series []float64) (r float64) { |
||||||
|
for _, v := range series { |
||||||
|
r += v |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
package ta |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
func TestPearson(t *testing.T) { |
||||||
|
s1 := []float64{1, 2, 3, 4} |
||||||
|
s2 := []float64{2, 4, 6, 8} |
||||||
|
s3 := []float64{8, 6, 4, 2} |
||||||
|
r, _ := Pearson(s1, s2) // 0.999 完美正相关
|
||||||
|
fmt.Println(r) |
||||||
|
r, _ = Pearson(s1, s3) // -0.999 完美负相关
|
||||||
|
fmt.Println(r) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func TestSpearman(t *testing.T) { |
||||||
|
x := []float64{10, 20, 30, 40, 50} |
||||||
|
y := []float64{15, 25, 20, 45, 50} |
||||||
|
r, _ := Spearman(x, y) |
||||||
|
fmt.Println(r) |
||||||
|
r, _ = Pearson(x, y) |
||||||
|
fmt.Println(r) |
||||||
|
} |
||||||
Loading…
Reference in new issue