fix: 收敛退出放宽到0.02%+净利为正, 恢复到0.02%即退不亏钱

This commit is contained in:
jackyu66git
2026-05-04 01:55:22 +08:00
parent 51b8ee0c8a
commit 1c0618583c
3 changed files with 88 additions and 4 deletions
+3 -2
View File
@@ -135,8 +135,9 @@ Round trip (2 legs entry + 2 legs exit): configurable, default **0.21%** total f
- `entering` map prevents duplicate entries on same coin
3. **Scale-in** adds another leg-worth when spread widens another `scale_step_pct` (default 0.10%)
4. **Exit** conditions (whichever hits first):
- **Net profit ≥ `take_profit_pct`** → **利润止盈**
- **Spread converges to ≤ 0 (prices equal or reversed)** → **价差收敛止盈**
- **Net profit ≥ `take_profit_pct`** → **利润止盈**(大盈利退出)
- **Spread narrowed to ≤ 0.02% + netPnl > 0** → **价差收敛止盈**(小盈利退出)
- **Spread flipped negative** → **价差反转平仓**(紧急止损)
- **Position held > `position_timeout_sec`** → **超时平仓**
5. **Direction**: BG → HL (buy BG, sell HL) or HL → BG (buy HL, sell BG)
+76
View File
@@ -0,0 +1,76 @@
// +build ignore
package main
import (
"encoding/json"
"fmt"
"log"
"net/url"
"time"
"github.com/gorilla/websocket"
)
func main() {
u := url.URL{Scheme: "wss", Host: "indexer.dydx.trade", Path: "/v4/ws"}
log.Printf("Connecting to %s", u.String())
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
done := make(chan struct{})
go func() {
defer close(done)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
return
}
log.Printf("recv: %s", string(message))
}
}()
// Subscribe
sub := map[string]string{"type": "subscribe", "channel": "v4_markets"}
subData, _ := json.Marshal(sub)
c.WriteMessage(websocket.TextMessage, subData)
log.Printf("sent sub: %s", string(subData))
// Try pings
for i := 0; i < 5; i++ {
time.Sleep(10 * time.Second)
// Try JSON ping
ping := map[string]string{"type": "ping"}
pingData, _ := json.Marshal(ping)
err := c.WriteMessage(websocket.TextMessage, pingData)
if err != nil {
log.Printf("JSON ping error: %v", err)
} else {
log.Printf("sent JSON ping: %s", string(pingData))
}
// Try raw WS ping frame
err = c.WriteMessage(websocket.PingMessage, []byte("ping"))
if err != nil {
log.Printf("WS ping error: %v", err)
} else {
log.Printf("sent WS ping frame")
}
}
time.Sleep(30 * time.Second)
fmt.Println("Done - checking if still connected")
select {
case <-done:
fmt.Println("Connection closed")
default:
fmt.Println("Still connected!")
}
}
+9 -2
View File
@@ -534,12 +534,19 @@ func (t *Trader) checkExit(pos *ArbPosition, bgP, hlP, diffPct float64, notifier
exitReason = "利润止盈"
}
// Exit when spread converges to zero or reverses (prices same or flipped)
if diffPct <= 0 {
// Convergence exit: spread narrowed significantly and we're profitable
// Prevents positions from sitting at near-zero spread waiting for timeout
if diffPct <= 0.02 && netPnl > 0 {
shouldExit = true
exitReason = "价差收敛止盈"
}
// Emergency reversal: spread flipped negative — cut losses
if diffPct < 0 {
shouldExit = true
exitReason = "价差反转平仓"
}
// Timeout: configured max hold time
if elapsed > t.cfg.PositionTimeout {
shouldExit = true