Browse Source

indicator/strategy input default

main
strange 7 months ago
parent
commit
cc687d6ea7
  1. 2
      internal/trading/backtest/sig_strategy_backtester.go
  2. 14
      internal/trading/sig/indicator_context.go
  3. 6
      pkg/indicator/macd.go
  4. 12
      pkg/strategy/super_trend_macd_rsi.go
  5. 90
      pkg/utils/security/aes.go
  6. 41
      pkg/utils/security/aes_test.go

2
internal/trading/backtest/sig_strategy_backtester.go

@ -62,6 +62,8 @@ func (b *SigStrategyBacktester) Backtest(ctx context.Context,
if intervalCandlePeriods == nil {
intervalCandlePeriods = types.NewIntervalState[int16]()
}
// 填充参数默认值
sig.FillDefaultInputs(sigStrategyInput, b.sigStrategy.Meta().Input)
// init sig strategy
if err = b.sigStrategy.Init(sigStrategyInput); err != nil {
return

14
internal/trading/sig/indicator_context.go

@ -39,6 +39,9 @@ type IndicatorContext struct {
}
func NewIndicatorContext(indicator indicator.IIndicator, input types.Input, indicatorStates IndicatorStates, kSeries *types.KlineSeries, indicatorsReg *indicator.IndicatorRegistry) *IndicatorContext {
// 指标参数默认值
FillDefaultInputs(input, indicator.Meta().Input)
inputs := collect.Mapping(indicator.Meta().Input, func(in types.InputArg) string {
return input.String(in.Name)
})
@ -169,3 +172,14 @@ windowLoop:
}
return
}
// FillDefaultInputs 填充指标参数默认值
func FillDefaultInputs(input types.Input, args []types.InputArg) {
for _, in := range args {
if in.Default != nil {
if _, ok := input[in.Name]; !ok {
input[in.Name] = in.Default
}
}
}
}

6
pkg/indicator/macd.go

@ -12,9 +12,9 @@ func (c *MACD) Meta() IndicatorMeta {
return IndicatorMeta{
Name: "MACD",
Input: []types.InputArg{
{Name: "fast", Type: types.InputTypeUInt, Desc: "快线周期"}, // 12
{Name: "slow", Type: types.InputTypeUInt, Desc: "慢线周期"}, // 26
{Name: "singal", Type: types.InputTypeUInt, Desc: "信号线周期"}, // 9
{Name: "fast", Type: types.InputTypeUInt, Desc: "快线周期", Default: 12}, // 12
{Name: "slow", Type: types.InputTypeUInt, Desc: "慢线周期", Default: 26}, // 26
{Name: "singal", Type: types.InputTypeUInt, Desc: "信号线周期", Default: 9}, // 9
},
State: []string{"dif", "dea"},
Plots: []Plot{

12
pkg/strategy/super_trend_macd_rsi.go

@ -22,12 +22,12 @@ func (s *SuperTrendMacdRSI) Meta() StrategyMeta {
Name: "SuperTrendMacdRSI",
Desc: "SuperTrend + MACD + RSI 量化策略",
Input: []types.InputArg{
{Name: "trendWindow", Type: types.InputTypeUInt, Desc: "SuperTrend ATR周期"}, // 10
{Name: "trendMul", Type: types.InputTypeUFloat, Desc: "SuperTrend multipiler"}, // 3
{Name: "rsi", Type: types.InputTypeUInt, Desc: "rsi周期"}, // 14
{Name: "fast", Type: types.InputTypeUInt, Desc: "macd fast period"}, // 12
{Name: "slow", Type: types.InputTypeUInt, Desc: "macd slow period"}, // 26
{Name: "singal", Type: types.InputTypeUInt, Desc: "macd singal period"}, // 9
{Name: "trendWindow", Type: types.InputTypeUInt, Desc: "SuperTrend ATR周期", Default: 10},
{Name: "trendMul", Type: types.InputTypeUFloat, Desc: "SuperTrend multipiler", Default: 3},
{Name: "rsi", Type: types.InputTypeUInt, Desc: "rsi周期", Default: 14},
{Name: "fast", Type: types.InputTypeUInt, Desc: "macd fast period", Default: 12},
{Name: "slow", Type: types.InputTypeUInt, Desc: "macd slow period", Default: 26},
{Name: "singal", Type: types.InputTypeUInt, Desc: "macd singal period", Default: 9},
},
}
}

90
pkg/utils/security/aes.go

@ -0,0 +1,90 @@
package security
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
)
func GenAesKey256() string {
key := genAesKey(256)
return base64.StdEncoding.EncodeToString(key)
}
func genAesKey(keySize int) []byte {
var key = make([]byte, keySize/8)
_, err := rand.Read(key)
if err != nil {
panic(err)
}
return key
}
// EncryptAesCBC
// src -> 要加密的原文
// key -> 秘钥, 和加密秘钥相同, 大小为: 8byte
func EncryptAesCBC(src, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 对最后一个明文分组进行数据填充
src = pkcs5Padding(src, blockSize)
// 3.创建一个密码分组为链接模式的,底层使用 DES 加密的 BlockMode 接口
// 参数 iv 的长度,必须等于 b 的块尺寸
iv := make([]byte, blockSize)
copy(iv, key)
blackMode := cipher.NewCBCEncrypter(block, iv)
// 5.加密连续的数据块
dst := make([]byte, len(src))
blackMode.CryptBlocks(dst, src)
return dst, nil
}
// DecryptAesCBC
// src -> 要解密的密文
// key -> 秘钥, 和加密秘钥相同, 大小为: 8byte
func DecryptAesCBC(src, key []byte) ([]byte, error) {
// 1. 创建并返回一个使用DES算法的cipher.Block接口
block, err := aes.NewCipher(key)
// 2. 判断是否创建成功
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 3. 创建一个密码分组为链接模式的, 底层使用DES解密的BlockMode接口
iv := make([]byte, blockSize)
copy(iv, key)
blockMode := cipher.NewCBCDecrypter(block, iv)
// 4. 解密数据
dst := src
blockMode.CryptBlocks(src, dst)
// 5. 去掉最后一组填充的数据
dst = pkcs5UnPadding(dst)
// 6. 返回结果
return dst, nil
}
// PKCS5Padding 使用pks5的方式填充
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
// 1. 计算最后一个分组缺多少个字节
padding := blockSize - (len(ciphertext) % blockSize)
// 2. 创建一个大小为padding的切片, 每个字节的值为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
// 3. 将padText添加到原始数据的后边, 将最后一个分组缺少的字节数补齐
newText := append(ciphertext, padText...)
return newText
}
// PKCS5UnPadding 删除pks5填充的尾部数据
func pkcs5UnPadding(origData []byte) []byte {
// 1. 计算数据的总长度
length := len(origData)
// 2. 根据填充的字节值得到填充的次数
number := int(origData[length-1])
// 3. 将尾部填充的number个字节去掉
return origData[:(length - number)]
}

41
pkg/utils/security/aes_test.go

@ -0,0 +1,41 @@
package security
import (
"encoding/base64"
"fmt"
"reflect"
"testing"
)
func TestGenAesKey256(t *testing.T) {
for range 10 {
key := GenAesKey256()
fmt.Println(key)
}
}
// 参考:https://www.yisu.com/zixun/696240.html
func TestAes(t *testing.T) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover...", r.(error).Error(), reflect.TypeOf(r))
}
}()
// aesKeyStr := GetAesKey256()
aesKeyStr := "VzKw8Vx+K8k1nO9fmPjhv8o+8l4vqpF+fjsbvXf0j4o="
fmt.Println(aesKeyStr)
key, _ := base64.StdEncoding.DecodeString(aesKeyStr)
text := []byte("hello sig.pub")
encrypt, _ := EncryptAesCBC(text, key)
fmt.Println(base64.URLEncoding.EncodeToString(text))
result, err := DecryptAesCBC(encrypt, key)
if err != nil {
t.Errorf("decrypt aes cbc failed: %v", err)
return
}
fmt.Println("result:", string(result))
}
Loading…
Cancel
Save