mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 08:46:58 +08:00
change v1
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user