feat: 手续费改为逐笔USD累算 + Vite React前端 + system_orders表 + README

This commit is contained in:
jackyu66git
2026-05-04 04:34:27 +08:00
parent 15a4684208
commit 0288dc8284
18 changed files with 2919 additions and 521 deletions
+34 -11
View File
@@ -7,6 +7,7 @@ import (
"log"
"math"
"net/http"
"os"
"sync"
"time"
@@ -217,8 +218,15 @@ func (d *Dashboard) Run() {
mux := http.NewServeMux()
staticSub, err := fs.Sub(staticFS, "web/static")
if err != nil {
// Try disk-based serving first (hot-reload friendly), fall back to embed
staticSub, err := fs.Sub(staticFS, "frontend/dist")
if diskFS := os.DirFS("frontend/dist"); true {
if _, diskErr := fs.Stat(diskFS, "index.html"); diskErr == nil {
staticSub = diskFS
log.Printf("[Web] Serving from disk: frontend/dist/ (hot reload enabled)")
}
}
if err != nil && staticSub == nil {
log.Printf("[Web] Failed to create static sub-fs: %v", err)
} else {
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticSub))))
@@ -379,19 +387,21 @@ func (d *Dashboard) broadcastLoop() {
longCurrent, shortCurrent = hlP, bgP
}
longAvg := weightedAvgPrice(pos.LongEntryPrices, pos.AmountUSD/float64(max(1, len(pos.LongEntryPrices))))
shortAvg := weightedAvgPrice(pos.ShortEntryPrices, pos.AmountUSD/float64(max(1, len(pos.ShortEntryPrices))))
longPnl := (longCurrent - longAvg) / longAvg * 100
shortPnl := (shortAvg - shortCurrent) / shortAvg * 100
totalFees := 2 * (takerFees[ExBitget] + takerFees[ExHyperLiquid])
netPnl := longPnl + shortPnl - totalFees
shortAvg := weightedAvgPrice(pos.ShortEntryPrices, pos.AmountUSD/float64(max(1, len(pos.ShortEntryPrices))))
longPnl := (longCurrent - longAvg) / longAvg * 100
shortPnl := (shortAvg - shortCurrent) / shortAvg * 100
feeEntryUSD := float64(1+pos.ScaleLevels) * (pos.AmountUSD / float64(max(1, 1+pos.ScaleLevels))) * (takerFees[ExBitget] + takerFees[ExHyperLiquid]) / 100
feeExitUSD := pos.AmountUSD * (takerFees[ExBitget] + takerFees[ExHyperLiquid]) / 100
pricePnLUSD := pos.AmountUSD * (longPnl + shortPnl) / 100
netPnLUSD := pricePnLUSD - feeEntryUSD - feeExitUSD
currentSpread := (hlP - bgP) / bgP * 100
if pos.LongLeg.Exchange == ExHyperLiquid {
currentSpread := (hlP - bgP) / bgP * 100
if pos.LongLeg.Exchange == ExHyperLiquid {
// HL→BG: spread positive when bgP > hlP
currentSpread = (bgP - hlP) / hlP * 100
}
posEntry["current_spread"] = math.Round(currentSpread*10000) / 10000
posEntry["pnl_est"] = math.Round(netPnl*10000) / 10000
posEntry["pnl_est"] = math.Round(netPnLUSD*10000) / 10000
}
}
@@ -519,7 +529,15 @@ func (d *Dashboard) BroadcastEvent(event string, data interface{}) {
// ============================================================
func (d *Dashboard) handleIndex(w http.ResponseWriter, r *http.Request) {
data, err := staticFS.ReadFile("web/static/index.html")
var data []byte
var err error
// Try disk first (hot reload)
data, err = os.ReadFile("frontend/dist/index.html")
if err != nil {
// Fall back to embed
data, err = staticFS.ReadFile("frontend/dist/index.html")
}
if err != nil {
http.Error(w, "Not found", 404)
return
@@ -602,6 +620,11 @@ func (d *Dashboard) handleTrades(w http.ResponseWriter, r *http.Request) {
page := 1
limit := 20
coin := r.URL.Query().Get("coin")
if l := r.URL.Query().Get("limit"); l != "" {
if n, err := fmt.Sscanf(l, "%d", &limit); err != nil || n != 1 {
limit = 20
}
}
trades, total, err := d.db.GetTrades(page, limit, coin)
if err != nil {
http.Error(w, err.Error(), 500)