diff --git a/market/timeframe.go b/market/timeframe.go index 752e441e..21fefd59 100644 --- a/market/timeframe.go +++ b/market/timeframe.go @@ -43,15 +43,6 @@ func TFDuration(tf string) (time.Duration, error) { return supportedTimeframes[norm], nil } -// MustNormalizeTimeframe is similar to NormalizeTimeframe, but panics when unsupported. -func MustNormalizeTimeframe(tf string) string { - norm, err := NormalizeTimeframe(tf) - if err != nil { - panic(err) - } - return norm -} - // SupportedTimeframes returns all supported timeframes (sorted slice). func SupportedTimeframes() []string { keys := make([]string, 0, len(supportedTimeframes)) diff --git a/trader/auto_trader_loop.go b/trader/auto_trader_loop.go index d7f4ae3e..3be8154b 100644 --- a/trader/auto_trader_loop.go +++ b/trader/auto_trader_loop.go @@ -47,7 +47,9 @@ func (at *AutoTrader) runCycle() error { at.logWarnf("⏸ Risk control: Trading paused, remaining %.0f minutes", remaining.Minutes()) record.Success = false record.ErrorMessage = fmt.Sprintf("Risk control paused, remaining %.0f minutes", remaining.Minutes()) - at.saveDecision(record) + if err := at.saveDecision(record); err != nil { + at.logWarnf("⚠ Failed to save decision record: %v", err) + } return nil } @@ -64,7 +66,9 @@ func (at *AutoTrader) runCycle() error { at.logErrorf("failed to build trading context: %v", err) record.Success = false record.ErrorMessage = fmt.Sprintf("Failed to build trading context: %v", err) - at.saveDecision(record) + if saveErr := at.saveDecision(record); saveErr != nil { + at.logWarnf("⚠ Failed to save decision record: %v", saveErr) + } return fmt.Errorf("failed to build trading context: %w", err) } @@ -84,7 +88,9 @@ func (at *AutoTrader) runCycle() error { PositionCount: ctx.Account.PositionCount, InitialBalance: at.initialBalance, } - at.saveDecision(record) + if err := at.saveDecision(record); err != nil { + at.logWarnf("⚠ Failed to save decision record: %v", err) + } return nil } @@ -157,7 +163,9 @@ func (at *AutoTrader) runCycle() error { } } - at.saveDecision(record) + if saveErr := at.saveDecision(record); saveErr != nil { + at.logWarnf("⚠ Failed to save decision record: %v", saveErr) + } // In safe mode, don't return error — keep the loop running to retry next cycle if at.safeMode { diff --git a/trader/bitget/trader_orders.go b/trader/bitget/trader_orders.go index f08a7a38..22fbbe73 100644 --- a/trader/bitget/trader_orders.go +++ b/trader/bitget/trader_orders.go @@ -14,7 +14,9 @@ func (t *BitgetTrader) OpenLong(symbol string, quantity float64, leverage int) ( symbol = t.convertSymbol(symbol) // Cancel old orders first - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -68,7 +70,9 @@ func (t *BitgetTrader) OpenShort(symbol string, quantity float64, leverage int) symbol = t.convertSymbol(symbol) // Cancel old orders first - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { diff --git a/trader/gate/trader_orders.go b/trader/gate/trader_orders.go index 198a6acb..49ab7e10 100644 --- a/trader/gate/trader_orders.go +++ b/trader/gate/trader_orders.go @@ -44,7 +44,9 @@ func (t *GateTrader) OpenLong(symbol string, quantity float64, leverage int) (ma symbol = t.convertSymbol(symbol) // Cancel old orders first - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -102,7 +104,9 @@ func (t *GateTrader) OpenShort(symbol string, quantity float64, leverage int) (m symbol = t.convertSymbol(symbol) // Cancel old orders first - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { diff --git a/trader/kucoin/trader_orders.go b/trader/kucoin/trader_orders.go index 41819202..e0d22c2d 100644 --- a/trader/kucoin/trader_orders.go +++ b/trader/kucoin/trader_orders.go @@ -14,7 +14,9 @@ import ( // OpenLong opens long position func (t *KuCoinTrader) OpenLong(symbol string, quantity float64, leverage int) (map[string]interface{}, error) { // Cancel old orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -69,7 +71,9 @@ func (t *KuCoinTrader) OpenLong(symbol string, quantity float64, leverage int) ( // OpenShort opens short position func (t *KuCoinTrader) OpenShort(symbol string, quantity float64, leverage int) (map[string]interface{}, error) { // Cancel old orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -218,7 +222,9 @@ func (t *KuCoinTrader) CloseLong(symbol string, quantity float64) (map[string]in logger.Infof("✓ KuCoin closed long position: %s", symbol) // Cancel pending orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel pending orders: %v", err) + } return map[string]interface{}{ "orderId": result.OrderId, @@ -299,7 +305,9 @@ func (t *KuCoinTrader) CloseShort(symbol string, quantity float64) (map[string]i logger.Infof("✓ KuCoin closed short position: %s", symbol) // Cancel pending orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel pending orders: %v", err) + } return map[string]interface{}{ "orderId": result.OrderId, diff --git a/trader/okx/trader_orders.go b/trader/okx/trader_orders.go index 2676db3f..ebe23115 100644 --- a/trader/okx/trader_orders.go +++ b/trader/okx/trader_orders.go @@ -12,7 +12,9 @@ import ( // OpenLong opens long position func (t *OKXTrader) OpenLong(symbol string, quantity float64, leverage int) (map[string]interface{}, error) { // Cancel old orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -91,7 +93,9 @@ func (t *OKXTrader) OpenLong(symbol string, quantity float64, leverage int) (map // OpenShort opens short position func (t *OKXTrader) OpenShort(symbol string, quantity float64, leverage int) (map[string]interface{}, error) { // Cancel old orders - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel old pending orders (may not have any): %v", err) + } // Set leverage if err := t.SetLeverage(symbol, leverage); err != nil { @@ -269,7 +273,9 @@ func (t *OKXTrader) CloseLong(symbol string, quantity float64) (map[string]inter logger.Infof("✓ OKX closed long position successfully: %s", symbol) // Cancel pending orders after closing position - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel pending orders: %v", err) + } return map[string]interface{}{ "orderId": orders[0].OrdId, @@ -383,7 +389,9 @@ func (t *OKXTrader) CloseShort(symbol string, quantity float64) (map[string]inte logger.Infof("✓ OKX closed short position successfully: %s, ordId=%s", symbol, orders[0].OrdId) // Cancel pending orders after closing position - t.CancelAllOrders(symbol) + if err := t.CancelAllOrders(symbol); err != nil { + logger.Infof(" ⚠ Failed to cancel pending orders: %v", err) + } return map[string]interface{}{ "orderId": orders[0].OrdId, diff --git a/web/package-lock.json b/web/package-lock.json index 09f2f565..186a676d 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -7039,9 +7039,9 @@ } }, "node_modules/react-router": { - "version": "7.13.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.2.tgz", - "integrity": "sha512-tX1Aee+ArlKQP+NIUd7SE6Li+CiGKwQtbS+FfRxPX6Pe4vHOo6nr9d++u5cwg+Z8K/x8tP+7qLmujDtfrAoUJA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.17.0.tgz", + "integrity": "sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -7061,12 +7061,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.13.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.2.tgz", - "integrity": "sha512-aR7SUORwTqAW0JDeiWF07e9SBE9qGpByR9I8kJT5h/FrBKxPMS6TiC7rmVO+gC0q52Bx7JnjWe8Z1sR9faN4YA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.17.0.tgz", + "integrity": "sha512-fyU2yjGups/hE6Xz0I5ZYbVL8Gx29eCjgpHaRaTaVU+OOAdfRX05KsvyRm0GO8YQwOkhpU3MurW1jyMUJn+zSw==", "license": "MIT", "dependencies": { - "react-router": "7.13.2" + "react-router": "7.17.0" }, "engines": { "node": ">=20.0.0"