From 099453e3bdff1aa8c66e774158d2510846308b57 Mon Sep 17 00:00:00 2001 From: sue <177699783@qq.com> Date: Thu, 30 Oct 2025 02:35:52 +0800 Subject: [PATCH 1/2] =?UTF-8?q?add=20=E5=B8=B8=E8=A7=81=E9=97=AE=E9=A2=98.?= =?UTF-8?q?md=20=E6=8F=90=E7=A4=BA=E5=A6=82=E4=BD=95=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=B8=81=E5=AE=89API=204061=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 常见问题.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 常见问题.md diff --git a/常见问题.md b/常见问题.md new file mode 100644 index 00000000..5d823205 --- /dev/null +++ b/常见问题.md @@ -0,0 +1,25 @@ +# 常见问题 + +## 币安持仓模式错误 (code=-4061) + +**错误信息**:`Order's position side does not match user's setting` + +**原因**:系统需要使用双向持仓模式,但您的币安账户设置为单向持仓。 + +### 解决方法 + +1. 登录 [币安合约交易平台](https://www.binance.com/zh-CN/futures/BTCUSDT) + +2. 点击右上角的 **⚙️ 偏好设置** + +3. 选择 **持仓模式** + +4. 切换为 **双向持仓** (Hedge Mode) + +5. 确认切换 + +**注意**:切换前必须先平掉所有持仓。 + +--- + +更多问题请查看 [GitHub Issues](https://github.com/tinkle-community/nofx/issues) From 3b4a4d34aa5725669d3a97cf60e5dd37f4726987 Mon Sep 17 00:00:00 2001 From: sue <177699783@qq.com> Date: Thu, 30 Oct 2025 02:43:14 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E9=97=AE=E9=A2=98=20##=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=86=85=E5=AE=B9=20###=201.=20AI=E5=86=B3=E7=AD=96?= =?UTF-8?q?=E6=9D=A0=E6=9D=86=E9=85=8D=E7=BD=AE=E5=8A=A8=E6=80=81=E5=8C=96?= =?UTF-8?q?=20(decision/engine.go)=20-=20**=E9=97=AE=E9=A2=98**:=20System?= =?UTF-8?q?=20Prompt=20=E4=B8=AD=E7=A1=AC=E7=BC=96=E7=A0=81=2050x/20x=20?= =?UTF-8?q?=E6=9D=A0=E6=9D=86=EF=BC=8C=E5=AF=BC=E8=87=B4=20AI=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=9A=84=E5=86=B3=E7=AD=96=E4=B8=8D=E7=AC=A6=E5=90=88?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=85=8D=E7=BD=AE=EF=BC=885x=EF=BC=89=20-=20?= =?UTF-8?q?**=E4=BF=AE=E5=A4=8D**:=20=20=20-=20buildSystemPrompt()=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20btcEthLeverage,=20altcoinLeverage=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0=20=20=20-=20System=20Prompt=20=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E4=BD=BF=E7=94=A8=E5=8A=A8=E6=80=81=E6=9D=A0=E6=9D=86?= =?UTF-8?q?=E5=80=BC=EF=BC=88=E7=AC=AC225-226=E8=A1=8C=EF=BC=89=20=20=20-?= =?UTF-8?q?=20=E7=A4=BA=E4=BE=8B=20JSON=20=E4=BD=BF=E7=94=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=9D=A0=E6=9D=86=E5=80=BC=EF=BC=88=E7=AC=AC299?= =?UTF-8?q?=E8=A1=8C=EF=BC=89=20=20=20-=20=E8=B0=83=E7=94=A8=E6=97=B6?= =?UTF-8?q?=E4=BC=A0=E5=85=A5=E5=AE=9E=E9=99=85=E9=85=8D=E7=BD=AE=E5=80=BC?= =?UTF-8?q?=EF=BC=88=E7=AC=AC100=E8=A1=8C=EF=BC=89=20-=20**=E5=BD=B1?= =?UTF-8?q?=E5=93=8D**:=20AI=20=E7=8E=B0=E5=9C=A8=E4=BC=9A=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E7=94=A8=E6=88=B7=E9=85=8D=E7=BD=AE=E7=9A=84=E6=9D=A0?= =?UTF-8?q?=E6=9D=86=E9=99=90=E5=88=B6=E7=94=9F=E6=88=90=E5=86=B3=E7=AD=96?= =?UTF-8?q?=20###=202.=20=E5=89=8D=E7=AB=AF=E5=88=9D=E5=A7=8B=E4=BD=99?= =?UTF-8?q?=E9=A2=9D=E6=98=BE=E7=A4=BA=E4=BC=98=E5=8C=96=20(web/src/compon?= =?UTF-8?q?ents/EquityChart.tsx)=20-=20**=E9=97=AE=E9=A2=98**:=20=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E4=BD=99=E9=A2=9D=E7=A1=AC=E7=BC=96=E7=A0=81=E4=B8=BA?= =?UTF-8?q?=201000=20USDT=EF=BC=8C=E4=B8=8E=E7=94=A8=E6=88=B7=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=9A=84=20100=20USDT=20=E4=B8=8D=E7=AC=A6=20-=20**?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D**:=20=E5=AE=9E=E7=8E=B0=E4=B8=89=E7=BA=A7?= =?UTF-8?q?=E5=9B=9E=E9=80=80=E6=9C=BA=E5=88=B6=20=20=201.=20=E4=BC=98?= =?UTF-8?q?=E5=85=88=E4=BD=BF=E7=94=A8=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E4=B8=AA=E7=82=B9=E7=9A=84=20total=5Fequity?= =?UTF-8?q?=20=20=202.=20=E5=A4=87=E7=94=A8=E4=BD=BF=E7=94=A8=E5=BD=93?= =?UTF-8?q?=E5=89=8D=E8=B4=A6=E6=88=B7=20account.total=5Fequity=20=20=203.?= =?UTF-8?q?=20=E6=9C=80=E5=90=8E=E4=BD=BF=E7=94=A8=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=80=BC=20100=EF=BC=88=E5=8C=B9=E9=85=8D=E5=B8=B8=E8=A7=81?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=89=20-=20**=E5=BD=B1=E5=93=8D**:=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E6=98=BE=E7=A4=BA=E7=9A=84=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E4=BD=99=E9=A2=9D=E7=8E=B0=E5=9C=A8=E4=B8=8E=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=B8=80=E8=87=B4=20##=20=E6=8A=80=E6=9C=AF?= =?UTF-8?q?=E7=BB=86=E8=8A=82=20**=E5=87=BD=E6=95=B0=E7=AD=BE=E5=90=8D?= =?UTF-8?q?=E5=8F=98=E6=9B=B4**:=20```go=20//=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=89=8D=20func=20buildSystemPrompt(accountEquity=20float64)?= =?UTF-8?q?=20string=20//=20=E4=BF=AE=E6=94=B9=E5=90=8E=20func=20buildSyst?= =?UTF-8?q?emPrompt(accountEquity=20float64,=20btcEthLeverage,=20altcoinLe?= =?UTF-8?q?verage=20int)=20string=20```=20**React=20=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E4=BC=98=E5=8C=96**:=20```typescript=20//=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=89=8D=20const=20initialBalance=20=3D=20history[0]=3F.total?= =?UTF-8?q?=5Fequity=20||=201000;=20//=20=E4=BF=AE=E6=94=B9=E5=90=8E=20con?= =?UTF-8?q?st=20initialBalance=20=3D=20history[0]=3F.total=5Fequity=20||?= =?UTF-8?q?=20account=3F.total=5Fequity=20||=20100;=20```=20Co-Authored-By?= =?UTF-8?q?:=20tinkle-community=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- decision/engine.go | 10 +++++----- web/src/components/EquityChart.tsx | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/decision/engine.go b/decision/engine.go index f6676196..a25f3644 100644 --- a/decision/engine.go +++ b/decision/engine.go @@ -97,7 +97,7 @@ func GetFullDecision(ctx *Context) (*FullDecision, error) { } // 2. 构建 System Prompt(固定规则)和 User Prompt(动态数据) - systemPrompt := buildSystemPrompt(ctx.Account.TotalEquity) + systemPrompt := buildSystemPrompt(ctx.Account.TotalEquity, ctx.BTCETHLeverage, ctx.AltcoinLeverage) userPrompt := buildUserPrompt(ctx) // 3. 调用AI API(使用 system + user prompt) @@ -200,7 +200,7 @@ func calculateMaxCandidates(ctx *Context) int { } // buildSystemPrompt 构建 System Prompt(固定规则,可缓存) -func buildSystemPrompt(accountEquity float64) string { +func buildSystemPrompt(accountEquity float64, btcEthLeverage, altcoinLeverage int) string { var sb strings.Builder // === 核心使命 === @@ -222,8 +222,8 @@ func buildSystemPrompt(accountEquity float64) string { sb.WriteString("# ⚖️ 硬约束(风险控制)\n\n") sb.WriteString("1. **风险回报比**: 必须 ≥ 1:3(冒1%风险,赚3%+收益)\n") sb.WriteString("2. **最多持仓**: 3个币种(质量>数量)\n") - sb.WriteString(fmt.Sprintf("3. **单币仓位**: 山寨%.0f-%.0f U(20x杠杆) | BTC/ETH %.0f-%.0f U(50x杠杆)\n", - accountEquity*0.8, accountEquity*1.5, accountEquity*5, accountEquity*10)) + sb.WriteString(fmt.Sprintf("3. **单币仓位**: 山寨%.0f-%.0f U(%dx杠杆) | BTC/ETH %.0f-%.0f U(%dx杠杆)\n", + accountEquity*0.8, accountEquity*1.5, altcoinLeverage, accountEquity*5, accountEquity*10, btcEthLeverage)) sb.WriteString("4. **保证金**: 总使用率 ≤ 90%\n\n") // === 做空激励 === @@ -296,7 +296,7 @@ func buildSystemPrompt(accountEquity float64) string { sb.WriteString("简洁分析你的思考过程\n\n") sb.WriteString("**第二步: JSON决策数组**\n\n") sb.WriteString("```json\n[\n") - sb.WriteString(fmt.Sprintf(" {\"symbol\": \"BTCUSDT\", \"action\": \"open_short\", \"leverage\": 50, \"position_size_usd\": %.0f, \"stop_loss\": 97000, \"take_profit\": 91000, \"confidence\": 85, \"risk_usd\": 300, \"reasoning\": \"下跌趋势+MACD死叉\"},\n", accountEquity*5)) + sb.WriteString(fmt.Sprintf(" {\"symbol\": \"BTCUSDT\", \"action\": \"open_short\", \"leverage\": %d, \"position_size_usd\": %.0f, \"stop_loss\": 97000, \"take_profit\": 91000, \"confidence\": 85, \"risk_usd\": 300, \"reasoning\": \"下跌趋势+MACD死叉\"},\n", btcEthLeverage, accountEquity*5)) sb.WriteString(" {\"symbol\": \"ETHUSDT\", \"action\": \"close_long\", \"reasoning\": \"止盈离场\"}\n") sb.WriteString("]\n```\n\n") sb.WriteString("**字段说明**:\n") diff --git a/web/src/components/EquityChart.tsx b/web/src/components/EquityChart.tsx index 505069b9..36f58342 100644 --- a/web/src/components/EquityChart.tsx +++ b/web/src/components/EquityChart.tsx @@ -80,8 +80,10 @@ export function EquityChart({ traderId }: EquityChartProps) { ? history.slice(-MAX_DISPLAY_POINTS) : history; - // 计算初始余额(使用第一个数据点) - const initialBalance = history[0]?.total_equity || 1000; + // 计算初始余额(使用第一个数据点,如果无数据则从account获取,最后才用默认值) + const initialBalance = history[0]?.total_equity + || account?.total_equity + || 100; // 默认值改为100,与常见配置一致 // 转换数据格式 const chartData = displayHistory.map((point) => {