mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-10 14:27:00 +08:00
refactor: rename decision package to kernel
This commit is contained in:
@@ -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"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user