refactor: rename decision package to kernel

This commit is contained in:
tinkle-community
2026-01-03 14:25:40 +08:00
parent d664dcca3d
commit 13fda47151
13 changed files with 76 additions and 76 deletions

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"sync"
"nofx/decision"
"nofx/kernel"
"nofx/market"
)
@@ -17,7 +17,7 @@ type cachedDecision struct {
Key string `json:"key"`
PromptVariant string `json:"prompt_variant"`
Timestamp int64 `json:"ts"`
Decision *decision.FullDecision `json:"decision"`
Decision *kernel.FullDecision `json:"decision"`
}
// AICache persists AI decisions for repeated backtesting or replay.
@@ -67,7 +67,7 @@ func (c *AICache) Path() string {
return c.path
}
func (c *AICache) Get(key string) (*decision.FullDecision, bool) {
func (c *AICache) Get(key string) (*kernel.FullDecision, bool) {
if c == nil || key == "" {
return nil, false
}
@@ -80,7 +80,7 @@ func (c *AICache) Get(key string) (*decision.FullDecision, bool) {
return cloneDecision(entry.Decision), true
}
func (c *AICache) Put(key string, variant string, ts int64, decision *decision.FullDecision) error {
func (c *AICache) Put(key string, variant string, ts int64, decision *kernel.FullDecision) error {
if c == nil || key == "" || decision == nil {
return nil
}
@@ -109,7 +109,7 @@ func (c *AICache) save() error {
return writeFileAtomic(c.path, data, 0o644)
}
func cloneDecision(src *decision.FullDecision) *decision.FullDecision {
func cloneDecision(src *kernel.FullDecision) *kernel.FullDecision {
if src == nil {
return nil
}
@@ -117,14 +117,14 @@ func cloneDecision(src *decision.FullDecision) *decision.FullDecision {
if err != nil {
return nil
}
var dst decision.FullDecision
var dst kernel.FullDecision
if err := json.Unmarshal(data, &dst); err != nil {
return nil
}
return &dst
}
func computeCacheKey(ctx *decision.Context, variant string, ts int64) (string, error) {
func computeCacheKey(ctx *kernel.Context, variant string, ts int64) (string, error) {
if ctx == nil {
return "", fmt.Errorf("context is nil")
}
@@ -132,9 +132,9 @@ func computeCacheKey(ctx *decision.Context, variant string, ts int64) (string, e
Variant string `json:"variant"`
Timestamp int64 `json:"ts"`
CurrentTime string `json:"current_time"`
Account decision.AccountInfo `json:"account"`
Positions []decision.PositionInfo `json:"positions"`
CandidateCoins []decision.CandidateCoin `json:"candidate_coins"`
Account kernel.AccountInfo `json:"account"`
Positions []kernel.PositionInfo `json:"positions"`
CandidateCoins []kernel.CandidateCoin `json:"candidate_coins"`
MarketData map[string]market.Data `json:"market"`
MarginUsedPct float64 `json:"margin_used_pct"`
Runtime int `json:"runtime_minutes"`

View File

@@ -13,7 +13,7 @@ import (
"sync"
"time"
"nofx/decision"
"nofx/kernel"
"nofx/market"
"nofx/mcp"
"nofx/store"
@@ -34,7 +34,7 @@ type Runner struct {
cfg BacktestConfig
feed *DataFeed
account *BacktestAccount
strategyEngine *decision.StrategyEngine
strategyEngine *kernel.StrategyEngine
decisionLogDir string
mcpClient mcp.AIClient
@@ -118,7 +118,7 @@ func NewRunner(cfg BacktestConfig, mcpClient mcp.AIClient) (*Runner, error) {
// Create strategy engine from backtest config for unified prompt generation
strategyConfig := cfg.ToStrategyConfig()
strategyEngine := decision.NewStrategyEngine(strategyConfig)
strategyEngine := kernel.NewStrategyEngine(strategyConfig)
r := &Runner{
cfg: cfg,
@@ -305,7 +305,7 @@ func (r *Runner) stepOnce() error {
record = rec
var (
fullDecision *decision.FullDecision
fullDecision *kernel.FullDecision
fromCache bool
cacheKey string
)
@@ -470,7 +470,7 @@ func (r *Runner) stepOnce() error {
return nil
}
func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Data, multiTF map[string]map[string]*market.Data, priceMap map[string]float64, callCount int) (*decision.Context, *store.DecisionRecord, error) {
func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Data, multiTF map[string]map[string]*market.Data, priceMap map[string]float64, callCount int) (*kernel.Context, *store.DecisionRecord, error) {
equity, unrealized, _ := r.account.TotalEquity(priceMap)
available := r.account.Cash()
marginUsed := r.totalMarginUsed()
@@ -479,7 +479,7 @@ func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Da
marginPct = (marginUsed / equity) * 100
}
accountInfo := decision.AccountInfo{
accountInfo := kernel.AccountInfo{
TotalEquity: equity,
AvailableBalance: available,
TotalPnL: equity - r.account.InitialBalance(),
@@ -495,14 +495,14 @@ func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Da
candidateCoins, err := r.strategyEngine.GetCandidateCoins()
if err != nil {
// Fallback to simple list if strategy engine fails
candidateCoins = make([]decision.CandidateCoin, 0, len(r.cfg.Symbols))
candidateCoins = make([]kernel.CandidateCoin, 0, len(r.cfg.Symbols))
for _, sym := range r.cfg.Symbols {
candidateCoins = append(candidateCoins, decision.CandidateCoin{Symbol: sym, Sources: []string{"backtest"}})
candidateCoins = append(candidateCoins, kernel.CandidateCoin{Symbol: sym, Sources: []string{"backtest"}})
}
}
runtime := int((ts - int64(r.cfg.StartTS*1000)) / 60000)
ctx := &decision.Context{
ctx := &kernel.Context{
CurrentTime: time.UnixMilli(ts).UTC().Format("2006-01-02 15:04:05 UTC"),
RuntimeMinutes: runtime,
CallCount: callCount,
@@ -566,7 +566,7 @@ func (r *Runner) buildDecisionContext(ts int64, marketData map[string]*market.Da
return ctx, record, nil
}
func (r *Runner) fillDecisionRecord(record *store.DecisionRecord, full *decision.FullDecision) {
func (r *Runner) fillDecisionRecord(record *store.DecisionRecord, full *kernel.FullDecision) {
record.InputPrompt = full.UserPrompt
record.CoTTrace = full.CoTTrace
if len(full.Decisions) > 0 {
@@ -576,12 +576,12 @@ func (r *Runner) fillDecisionRecord(record *store.DecisionRecord, full *decision
}
}
func (r *Runner) invokeAIWithRetry(ctx *decision.Context) (*decision.FullDecision, error) {
func (r *Runner) invokeAIWithRetry(ctx *kernel.Context) (*kernel.FullDecision, error) {
var lastErr error
for attempt := 0; attempt < aiDecisionMaxRetries; attempt++ {
// Use GetFullDecisionWithStrategy with the pre-configured strategy engine
// This ensures backtest uses the same unified prompt generation as live trading
fd, err := decision.GetFullDecisionWithStrategy(
fd, err := kernel.GetFullDecisionWithStrategy(
ctx,
r.mcpClient,
r.strategyEngine,
@@ -597,7 +597,7 @@ func (r *Runner) invokeAIWithRetry(ctx *decision.Context) (*decision.FullDecisio
return nil, lastErr
}
func (r *Runner) executeDecision(dec decision.Decision, priceMap map[string]float64, ts int64, cycle int) (store.DecisionAction, []TradeEvent, string, error) {
func (r *Runner) executeDecision(dec kernel.Decision, priceMap map[string]float64, ts int64, cycle int) (store.DecisionAction, []TradeEvent, string, error) {
symbol := dec.Symbol
usedLeverage := r.resolveLeverage(dec.Leverage, symbol)
actionRecord := store.DecisionAction{
@@ -739,7 +739,7 @@ func (r *Runner) executeDecision(dec decision.Decision, priceMap map[string]floa
}
}
func (r *Runner) determineQuantity(dec decision.Decision, price float64) float64 {
func (r *Runner) determineQuantity(dec kernel.Decision, price float64) float64 {
snapshot := r.snapshotState()
equity := snapshot.Equity
if equity <= 0 {
@@ -777,7 +777,7 @@ func (r *Runner) determineQuantity(dec decision.Decision, price float64) float64
return qty
}
func (r *Runner) determineCloseQuantity(symbol, side string, dec decision.Decision) float64 {
func (r *Runner) determineCloseQuantity(symbol, side string, dec kernel.Decision) float64 {
for _, pos := range r.account.Positions() {
if pos.Symbol == strings.ToUpper(symbol) && pos.Side == side {
return pos.Quantity
@@ -831,12 +831,12 @@ func (r *Runner) snapshotPositions(priceMap map[string]float64) []store.Position
return list
}
func (r *Runner) convertPositions(priceMap map[string]float64) []decision.PositionInfo {
func (r *Runner) convertPositions(priceMap map[string]float64) []kernel.PositionInfo {
positions := r.account.Positions()
list := make([]decision.PositionInfo, 0, len(positions))
list := make([]kernel.PositionInfo, 0, len(positions))
for _, pos := range positions {
price := priceMap[pos.Symbol]
list = append(list, decision.PositionInfo{
list = append(list, kernel.PositionInfo{
Symbol: pos.Symbol,
Side: pos.Side,
EntryPrice: pos.EntryPrice,
@@ -1416,7 +1416,7 @@ func snapshotsToMap(snaps []PositionSnapshot) map[string]PositionSnapshot {
return positions
}
func sortDecisionsByPriority(decisions []decision.Decision) []decision.Decision {
func sortDecisionsByPriority(decisions []kernel.Decision) []kernel.Decision {
if len(decisions) <= 1 {
return decisions
}
@@ -1434,7 +1434,7 @@ func sortDecisionsByPriority(decisions []decision.Decision) []decision.Decision
}
}
result := make([]decision.Decision, len(decisions))
result := make([]kernel.Decision, len(decisions))
copy(result, decisions)
sort.Slice(result, func(i, j int) bool {