Browse Source

strategy candle periods

main
strange 9 months ago
parent
commit
b93a631d76
  1. 2
      README.md
  2. 2
      internal/sig/sig_server.go
  3. 8
      internal/trading/backtest/sig_strategy_backtester.go
  4. 2
      pkg/strategy/cross_star.go
  5. 50
      pkg/strategy/gold_x.go
  6. 4
      pkg/strategy/sig_strategy.go
  7. 4
      pkg/strategy/super_trend.go

2
README.md

@ -86,3 +86,5 @@ strategy0: 趋势追踪,增长趋势,
[investing-algorithm-framework](https://github.com/coding-kitties/investing-algorithm-framework)
回测信号可视化, /trading/strategySeries 一样从postgres拉信号/订单数据
go plugin插件化(指标/策略), docker中运行回测

2
internal/sig/sig_server.go

@ -94,7 +94,7 @@ func (s *SigServer) handleGrpcGenericCall(c *gin.Context) {
// put session
ctx := context.Background()
ctx = session.PutSubject(ctx, session.NewRpcSubject("123456"))
ctx, cancel = context.WithTimeout(ctx, time.Second*10)
ctx, cancel = context.WithTimeout(ctx, time.Second*20)
defer cancel()
// todo config call options

8
internal/trading/backtest/sig_strategy_backtester.go

@ -75,7 +75,7 @@ func (b *SigStrategyBacktester) singleStrategySeries(ctx context.Context, sigStr
interval := types.Interval(sr.Interval)
kSeries := intervalKlineSeries.ComputeIfAbsent(interval, func() *sig.KlineSeries { return sig.NewKlineSeries(sr.Exchange, sr.InstId, interval) })
strategyContext := sig.NewStrategyContext(sigStrategyInput, kSeries, b.indicatorReg)
requiredSeries := int(sigStrategy.RequiredSeries(sigStrategyInput))
requiredSeries := int(sigStrategy.CandlePeriods(strategyContext))
requiredIntervalSeries := types.NewIntervalState[int16]()
requiredIntervalSeries.Set(interval, int16(max(1, requiredSeries)))
@ -101,10 +101,10 @@ func (b *SigStrategyBacktester) singleStrategySeries(ctx context.Context, sigStr
// intervalStrategySeries 多周期策略
func (b *SigStrategyBacktester) intervalStrategySeries(ctx context.Context, intervalSigStrategy strategy.IIntervalSigStrategy, sigStrategyInput types.Input, sr *pb.SeriesRange, intervalKlineSeries *types.IntervalState[*sig.KlineSeries], recvSignal func(sigSide types.Side, k types.Kline) (err error)) (err error) {
// 各周期所需k线数量
requiredIntervalSeries := intervalSigStrategy.RequiredIntervalSeries(sigStrategyInput)
// 策略上下文
intervalStrategyContext := sig.NewIntervalStrategyContext(sigStrategyInput, intervalKlineSeries, b.indicatorReg)
// 各周期所需k线数量
requiredIntervalSeries := intervalSigStrategy.CandlePeriods(intervalStrategyContext)
err = b.multiIntervalSeries(ctx, sr, requiredIntervalSeries, intervalKlineSeries, func(driver bool, interval types.Interval, k *types.Kline) (err error) {
if !driver {
return
@ -332,7 +332,7 @@ func (b *SigStrategyBacktester) _singleStrategySeries(ctx context.Context, sigSt
kSeries := sig.NewKlineSeries(sr.Exchange, sr.InstId, interval)
strategyContext := sig.NewStrategyContext(nil, kSeries, b.indicatorReg)
requiredSeries := int(sigStrategy.RequiredSeries(nil))
requiredSeries := int(sigStrategy.CandlePeriods(nil))
sr.WindowExtra = uint32(max(0, requiredSeries-1))
err = b.fetchHistoryKlineSeries(ctx, sr, func(k *types.Kline) (err error) {
if lastTs, serial := kSeries.Update(k); !serial {

2
pkg/strategy/cross_star.go

@ -34,7 +34,7 @@ func (s *CrossStar) Init(input types.Input) (err error) { // 校验参数, 并
return
}
func (s *CrossStar) RequiredIntervalSeries(input types.Input) (iss *types.IntervalState[int16]) {
func (s *CrossStar) CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) {
iss = types.NewIntervalState[int16]()
iss.Set(types.Interval5m, 1)
iss.Set(types.Interval15m, 2)

50
pkg/strategy/gold_x.go

@ -1,14 +1,12 @@
package strategy
import (
"fmt"
"sig-pub/pkg/types"
)
// GoldX 金叉策略
type GoldX struct {
ISigStrategy
short, long int16
}
func (s *GoldX) New() ISigStrategy {
@ -20,39 +18,47 @@ func (s *GoldX) Meta() StrategyMeta {
Name: "GoldX",
Desc: "金叉策略",
Input: []types.InputArg{
{Name: "short", Type: types.InputTypeUInt, Desc: "短周期"},
{Name: "long", Type: types.InputTypeUInt, Desc: "长周期"},
{Name: "fast", Type: types.InputTypeUInt, Desc: "macd快线周期"},
{Name: "slow", Type: types.InputTypeUInt, Desc: "macd慢线周期"},
{Name: "singal", Type: types.InputTypeUInt, Desc: "macd信号线周期"},
},
}
}
func (s *GoldX) Init(input types.Input) (err error) { // 校验参数, 并根据参数初始化策略
s.short = input.Int16("short")
s.long = input.Int16("long")
if s.long <= s.short {
err = fmt.Errorf("param short should bigger then short")
return
}
// Init 校验参数, 并根据参数初始化策略
func (s *GoldX) Init(input types.Input) (err error) {
return
}
func (s *GoldX) RequiredSeries(input types.Input) int16 {
return max(s.long, s.short) + 1
func (s *GoldX) CandlePeriods(ctx ISingleSigStrategyContext) int16 {
return max(
ctx.Indicator("macd", ctx.Input()).CandlePeriods(),
ctx.Indicator("macd_dea", ctx.Input()).CandlePeriods(),
ctx.Indicator("macd_hist", ctx.Input()).CandlePeriods(),
)
}
func (s *GoldX) Update(ctx ISingleSigStrategyContext) (side types.Side) {
sma14 := ctx.Indicator("sma", s.short)
sma28 := ctx.Indicator("sma", s.long)
// 包装方法 crossover/crossunder
s14 := sma14.Series(0, 2)
s28 := sma28.Series(0, 2)
crossover := s14[0] > s28[0] && s14[1] < s28[1] // 上穿
crossunder := s14[0] < s28[0] && s14[1] > s28[1] // 下穿
macd := ctx.Indicator("macd", ctx.Input()).Series(0, 2) // macd线
macdDea := ctx.Indicator("macd_dea", ctx.Input()).Series(0, 2) // macd信号线
macdHist := ctx.Indicator("macd_hist", ctx.Input()).Get(0) // macd柱状图
// todo 包装方法 crossover/crossunder
// 1.MACD 线接近或上穿零轴(表示整体多头市场)
crossover := macd[0] > macdDea[0] && macd[1] < macdDea[1] // 上穿
crossunder := macd[0] < macdDea[0] && macd[1] > macdDea[1] // 下穿
if crossover {
return types.SideLong
// 2.附加确认条件: 柱状图从负值转为正值
if macdHist > 0 {
// todo 3.成交量放大(结合 OBV 等指标验证资金流入)。
return types.SideLong
}
}
if crossunder {
return types.SideShort
if macdHist < 0 {
return types.SideShort
}
}
return
}

4
pkg/strategy/sig_strategy.go

@ -22,7 +22,7 @@ type StrategyMeta struct {
// ISingleSigStrategy 单周期单交易所策略
type ISingleSigStrategy interface {
ISigStrategy
RequiredSeries(input types.Input) int16 // 需要的最小数据k线数, 回测时用, 若不定义则取最大窗口值
CandlePeriods(ctx ISingleSigStrategyContext) int16 // 需要的最小数据k线数, 回测时用, 若不定义则取最大窗口值
Update(ctx ISingleSigStrategyContext) (side types.Side)
}
@ -41,7 +41,7 @@ type ISingleSigStrategyContext interface {
// 多周期k线策略接口
type IIntervalSigStrategy interface {
ISigStrategy
RequiredIntervalSeries(input types.Input) (iss *types.IntervalState[int16]) // 需要的各周期最小数据k线数, 回测时用, 若不定义则取最大窗口值
CandlePeriods(ctx IIntervalSigStrategyContext) (iss *types.IntervalState[int16]) // 需要的各周期最小数据k线数, 回测时用, 若不定义则取最大窗口值
Update(ctx IIntervalSigStrategyContext) (side types.Side)
}

4
pkg/strategy/super_trend.go

@ -56,8 +56,8 @@ func (s *SupertrendBOSWaves) Init(input types.Input) (err error) { // 校验参
return
}
func (s *SupertrendBOSWaves) RequiredSeries(input types.Input) int16 {
return s.atrLength + 1
func (s *SupertrendBOSWaves) CandlePeriods(ctx ISingleSigStrategyContext) int16 {
return ctx.Input().Int16("atrLength") + 1
}
func (s *SupertrendBOSWaves) Update(ctx ISingleSigStrategyContext) (side types.Side) {

Loading…
Cancel
Save