feat: 手续费改为逐笔USD累算 + Vite React前端 + system_orders表 + README
This commit is contained in:
+34
-11
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user