fix: 收敛退出放宽到0.02%+净利为正, 恢复到0.02%即退不亏钱
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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!")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user