change v1

This commit is contained in:
lky-spec
2026-04-25 16:18:45 +08:00
parent 737f9bca95
commit c244e4cdf1
89 changed files with 17382 additions and 6198 deletions

View File

@@ -6,13 +6,15 @@ import (
"log/slog"
"nofx/safe"
"strings"
"sync"
"time"
)
type Scheduler struct {
agent *Agent
logger *slog.Logger
stopCh chan struct{}
agent *Agent
logger *slog.Logger
stopCh chan struct{}
stopOnce sync.Once
}
func NewScheduler(a *Agent, l *slog.Logger) *Scheduler {
@@ -27,8 +29,10 @@ func (s *Scheduler) Start(ctx context.Context) {
lastCheck := time.Time{}
for {
select {
case <-ctx.Done(): return
case <-s.stopCh: return
case <-ctx.Done():
return
case <-s.stopCh:
return
case now := <-ticker.C:
// Daily report at 21:00
if now.Hour() == 21 && now.Sub(lastReport) > 12*time.Hour {
@@ -51,13 +55,21 @@ func (s *Scheduler) Start(ctx context.Context) {
})
}
func (s *Scheduler) Stop() { close(s.stopCh) }
func (s *Scheduler) Stop() {
s.stopOnce.Do(func() {
close(s.stopCh)
})
}
func (s *Scheduler) dailyReport() {
if s.agent.traderManager == nil { return }
if s.agent.traderManager == nil {
return
}
traders := s.agent.traderManager.GetAllTraders()
if len(traders) == 0 { return }
if len(traders) == 0 {
return
}
var sb strings.Builder
sb.WriteString(fmt.Sprintf("📊 *NOFXi 每日报告 — %s*\n\n", time.Now().Format("2006-01-02")))
@@ -65,30 +77,40 @@ func (s *Scheduler) dailyReport() {
totalPnL := 0.0
for _, t := range traders {
info, err := t.GetAccountInfo()
if err != nil { continue }
if err != nil {
continue
}
equity := toFloat(info["total_equity"])
pnl := toFloat(info["unrealized_pnl"])
sb.WriteString(fmt.Sprintf("• %s: $%.2f (P/L: $%.2f)\n", t.GetName(), equity, pnl))
totalPnL += pnl
}
e := "📈"
if totalPnL < 0 { e = "📉" }
if totalPnL < 0 {
e = "📉"
}
sb.WriteString(fmt.Sprintf("\n%s Total P/L: $%.2f", e, totalPnL))
s.agent.notifyAll(sb.String())
}
func (s *Scheduler) riskCheck() {
if s.agent.traderManager == nil { return }
if s.agent.traderManager == nil {
return
}
var alerts []string
for _, t := range s.agent.traderManager.GetAllTraders() {
positions, err := t.GetPositions()
if err != nil { continue }
if err != nil {
continue
}
for _, p := range positions {
pnl := toFloat(p["unrealizedPnl"])
size := toFloat(p["size"])
if size == 0 { continue }
if size == 0 {
continue
}
entry := toFloat(p["entryPrice"])
if entry > 0 {
pnlPct := (pnl / (entry * size)) * 100