Browse Source

trade analyzer refactor

main
strange 7 months ago
parent
commit
8c6c927168
  1. 28
      internal/trading/backtest/trading_plan_backtester.go
  2. 60
      pkg/trade/itrade_analyzer.go
  3. 17
      pkg/trade/kelly_trade_strategy.go
  4. 8
      pkg/trade/sig_trade_exit_strategy.go
  5. 12
      pkg/trade/sig_trade_strategy.go
  6. 61
      pkg/trade/trade_strategy.go

28
internal/trading/backtest/trading_plan_backtester.go

@ -31,9 +31,7 @@ type TradingPlanBacktester struct {
sigStrategyInput types.Input sigStrategyInput types.Input
tradeStrategyInput types.Input tradeStrategyInput types.Input
closeStrategy trade.ICloseStrategy tradeAnalyzer trade.ITradeAnalyzer
riskStrategy trade.IRiskStrategy
tradeStrategy trade.ITradeStrategy
instanceIntervalSigStrategyContext strategy.IInstanceIntervalSigStrategyContext instanceIntervalSigStrategyContext strategy.IInstanceIntervalSigStrategyContext
} }
@ -84,12 +82,8 @@ func (b *TradingPlanBacktester) Init(cash float64, plan entity.TradePlan, sr *pb
if err = tradeStrate.Init(b.tradeStrategyInput); err != nil { if err = tradeStrate.Init(b.tradeStrategyInput); err != nil {
return return
} }
// 平仓策略 // 交易分析器
b.closeStrategy = tradeStrate b.tradeAnalyzer = tradeStrate
// 风险管理策略
b.riskStrategy = tradeStrate
// 交易策略
b.tradeStrategy = tradeStrate
return return
} }
@ -236,7 +230,7 @@ func (b *TradingPlanBacktester) forceCloseAllHoldingPosition() (err error) {
// closeByKlineInterval1m k线更新时检查平仓 // closeByKlineInterval1m k线更新时检查平仓
func (b *TradingPlanBacktester) closeByKlineInterval1m(instId string, k types.Kline) (err error) { func (b *TradingPlanBacktester) closeByKlineInterval1m(instId string, k types.Kline) (err error) {
price := decimals.MustToFloat64(k.Close) price := decimals.MustToFloat64(k.Close)
closeTickets, err := b.closeStrategy.CloseAssessOnPrice(b.instanceIntervalSigStrategyContext, b.account, instId, price) closeTickets, err := b.tradeAnalyzer.ExitAnalysisOnPrice(b.instanceIntervalSigStrategyContext, b.account, instId, price)
if err != nil { if err != nil {
return return
} }
@ -255,7 +249,7 @@ func (b *TradingPlanBacktester) closeByKlineInterval1m(instId string, k types.Kl
// closeBySigSingal 交易信号出现时检查平仓 // closeBySigSingal 交易信号出现时检查平仓
func (b *TradingPlanBacktester) closeBySigSingal(instId string, sigSide types.Side, _ types.Kline) (err error) { func (b *TradingPlanBacktester) closeBySigSingal(instId string, sigSide types.Side, _ types.Kline) (err error) {
closeTickets, err := b.closeStrategy.CloseAssessOnSig(b.instanceIntervalSigStrategyContext, b.account, instId, sigSide) closeTickets, err := b.tradeAnalyzer.ExitAnalysisOnSig(b.instanceIntervalSigStrategyContext, b.account, instId, sigSide)
if err != nil { if err != nil {
return return
} }
@ -275,16 +269,8 @@ func (b *TradingPlanBacktester) closeBySigSingal(instId string, sigSide types.Si
// onSideSingal 出现买卖信号 // onSideSingal 出现买卖信号
func (b *TradingPlanBacktester) onSideSingal(instId string, sigSide types.Side, _ types.Kline) (err error) { func (b *TradingPlanBacktester) onSideSingal(instId string, sigSide types.Side, _ types.Kline) (err error) {
// 买卖信号交易风险分析 tickets, skipCause, err := b.tradeAnalyzer.EntryAnalysis(b.instanceIntervalSigStrategyContext, b.account, instId, sigSide)
doTrade, causes, err := b.riskStrategy.RishAssess(b.instanceIntervalSigStrategyContext, b.account, instId, sigSide) _ = skipCause // todo 记录信号不交易原因 log db analyze
if err != nil {
return
}
if !doTrade {
_ = causes // todo 记录信号不交易原因分析 log db analyze
return
}
tickets, err := b.tradeStrategy.TradeAssess(b.instanceIntervalSigStrategyContext, b.account, instId, sigSide)
if err != nil || len(tickets) == 0 { if err != nil || len(tickets) == 0 {
return return
} }

60
pkg/trade/itrade_analyzer.go

@ -0,0 +1,60 @@
package trade
import (
"sig-pub/pkg/strategy"
"sig-pub/pkg/types"
"github.com/govalues/decimal"
)
// ITradeAnalyzer 建仓到平仓分析器
type ITradeAnalyzer interface {
IEntryAnalyzer
IExitAnalyzer
// Init 校验参数, 并根据参数初始化策略
Init(input types.Input) (err error)
}
// IEntryAnalyzer 建仓下单策略
type IEntryAnalyzer interface {
strategy.ISigStrategy
// 需要的各周期最小数据k线数
CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16])
// EntryAnalysis 生成下单参数(交易量/方向/杠杆) 建仓分析:确定是否入场、下单价格及仓位大小
// 币种持仓中不能改变杠杆
// tickets 建仓单信息
// skipCause 跳过交易信号原因
EntryAnalysis(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (tickets []TradeTicket, skipCause Cause, err error)
}
// IExitAnalyzer 平仓评估评估、止盈止损策略(trading service 管理)
type IExitAnalyzer interface {
strategy.ISigStrategy
// 需要的各周期最小数据k线数
CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16])
// ExitAnalysisOnPrice 价格更新评估是否平仓
// @return closeTicket平仓单信息
ExitAnalysisOnPrice(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, price float64) (closeTickets []TradeTicket, err error)
// ExitAnalysisOnSig 信号触发时评估是否平仓
ExitAnalysisOnSig(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, sigSide types.Side) (closeTickets []TradeTicket, err error)
}
type TradeTicket struct {
TradeType TradeType
InstId string
Side types.Side // 开仓方向
Price float64 // 开仓价格
Leverage int32 // 杠杆倍数
Qty decimal.Decimal // 交易量 qty为交易产品数量 todo decimal
Interval string // k线周期
Ktime int64 // k线时间
Ctime int64 // 创建时间(ctime-ktime=信号延迟)
Cause Cause
TradesId []int64 // 关联交易订单id (仅平仓使用)
}

17
pkg/trade/kelly_trade_strategy.go

@ -0,0 +1,17 @@
package trade
// 1. 基于风险敞口的策略 (Risk-Based Sizing)
// 1.1 固定风险金额模型 (Fixed Fractional Risk)
// 1.2 波动率倒数模型 (Volatility Targeting / ATR Sizing)
// 2. 基于资金占比的策略 (Equity-Based Sizing)
// 2.1 固定资金比例 (Fixed Percentage of Capital)
// 2.2 最大持仓限制 (Max Position Constraints)
// 3. 基于胜率与信号的策略 (Probability & Signal Based)
// 3.1 凯利公式 (The Kelly Criterion)
// 3.2 信号强度加权 (Signal Strength Weighting)
// 策略名称,适用场景,优点,缺点,推荐指数
// 固定风险金额,趋势跟踪、波段交易,风险恒定,极度稳健,防守性强,计算稍繁琐,需严格设止损,⭐⭐⭐⭐⭐ (首选)
// ATR波动率模型,多品种CTA、资产组合,平滑不同品种间的波动差异,对ATR参数敏感,⭐⭐⭐⭐⭐ (机构首选)
// 固定资金比例,股票长线投资,简单直观,便于执行,忽略了品种的风险差异,⭐⭐⭐
// 凯利公式,高频交易、高胜率策略,理论收益最大化,风险极高,极易破产,⭐⭐ (仅限高手)

8
pkg/trade/sig_close_strategy.go → pkg/trade/sig_trade_exit_strategy.go

@ -7,9 +7,9 @@ import (
"time" "time"
) )
// CloseAssess 价格更新评估是否平仓 // ExitAnalysis 价格更新评估是否平仓
// @return closeTicket平仓单信息 // @return closeTicket平仓单信息
func (s *SigTradeStrategy) CloseAssessOnPrice(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, price float64) (closeTickets []TradeTicket, err error) { func (s *SigTradeStrategy) ExitAnalysisOnPrice(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, price float64) (closeTickets []TradeTicket, err error) {
openTrades := account.GetOpenTrades(instId) openTrades := account.GetOpenTrades(instId)
if len(openTrades) == 0 { if len(openTrades) == 0 {
return return
@ -120,8 +120,8 @@ func (s *SigTradeStrategy) closeTradeOnPrice(price float64, trd *TradeOrder) (cl
return return
} }
// CloseAssessOnSig 信号触发时评估是否平仓 // ExitAnalysis 信号触发时评估是否平仓
func (s *SigTradeStrategy) CloseAssessOnSig(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, sigSide types.Side) (closeTickets []TradeTicket, err error) { func (s *SigTradeStrategy) ExitAnalysisOnSig(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, sigSide types.Side) (closeTickets []TradeTicket, err error) {
if !s.closeParam.CloseOnSideReverse { if !s.closeParam.CloseOnSideReverse {
return return
} }

12
pkg/trade/sig_trade_strategy.go

@ -64,16 +64,12 @@ func (s *SigTradeStrategy) CandlePeriods(ctx strategy.IInstanceIntervalSigStrate
return return
} }
// RishAssess 信号风险评估, 是否进行交易 // EntryAnalysis 生成下单参数(交易量/方向/杠杆)
func (s *SigTradeStrategy) RishAssess(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (doTrade bool, cause Cause, err error) {
return true, 0, nil
}
// TradeAssess 生成下单参数(交易量/方向/杠杆)
// 控制滑点, 仓位管理 // 控制滑点, 仓位管理
// 持仓中币种不能改变杠杆 // 持仓中币种不能改变杠杆
func (s *SigTradeStrategy) TradeAssess(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (tickets []TradeTicket, err error) { func (s *SigTradeStrategy) EntryAnalysis(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (tickets []TradeTicket, skipCause Cause, err error) {
// todo 买卖信号交易风险分析
if pos := account.GetPosition(sigInstId); pos != nil { if pos := account.GetPosition(sigInstId); pos != nil {
// 已持仓不能下反方向单, todo 副账户做反方向单,对冲(viceAccount) // 已持仓不能下反方向单, todo 副账户做反方向单,对冲(viceAccount)
if pos.Side != sigSide { if pos.Side != sigSide {

61
pkg/trade/trade_strategy.go

@ -1,61 +0,0 @@
package trade
import (
"sig-pub/pkg/strategy"
"sig-pub/pkg/types"
"github.com/govalues/decimal"
)
// IRiskStrategy 风险控制接口
type IRiskStrategy interface {
strategy.ISigStrategy
// 需要的各周期最小数据k线数
CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16])
// RishAssess 信号风险评估, 是否进行交易
RishAssess(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (ok bool, cause Cause, err error)
}
// ITradeStrategy 下单策略
type ITradeStrategy interface {
strategy.ISigStrategy
// 需要的各周期最小数据k线数
CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16])
// TradeAssess 生成下单参数(交易量/方向/杠杆)
// 控制滑点, 仓位管理
// 持仓中币种不能改变杠杆
TradeAssess(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (tickets []TradeTicket, err error)
}
// Exit 止盈止损策略(trading service 管理)
type ICloseStrategy interface {
strategy.ISigStrategy
// 需要的各周期最小数据k线数
CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16])
// CloseAssess 价格更新评估是否平仓
// @return closeTicket平仓单信息
CloseAssessOnPrice(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, price float64) (closeTickets []TradeTicket, err error)
// CloseAssessOnSig 信号触发时评估是否平仓
CloseAssessOnSig(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, instId string, sigSide types.Side) (closeTickets []TradeTicket, err error)
}
type TradeTicket struct {
TradeType TradeType
InstId string
Side types.Side // 开仓方向
Price float64 // 开仓价格
Leverage int32 // 杠杆倍数
Qty decimal.Decimal // 交易量 qty为交易产品数量 todo decimal
Interval string // k线周期
Ktime int64 // k线时间
Ctime int64 // 创建时间(ctime-ktime=信号延迟)
Cause Cause
TradesId []int64 // 关联交易订单id (仅平仓使用)
}
Loading…
Cancel
Save