如何解决Pine Script多品种策略胜率筛选器失效问题
问题诊断
你代码里的GetWinRate()函数调用的是全局的strategy.wintrades和strategy.closedtrades,这两个变量统计的是整个策略的所有交易数据,不是单个品种的。因为你在getsymbolRate里执行的所有交易操作都会被合并到主策略的交易记录中,所以每个品种返回的胜率其实是同一个全局值,无法区分单个品种的胜负情况。
解决方案
需要为每个品种单独维护交易统计变量,在每个品种的逻辑里自行记录盈利交易数、总平仓交易数,而不是依赖全局的策略变量。以下是修改后的完整代码:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © amjupvc1234 //@version=5 strategy("Table", overlay=true) // 自定义胜率计算,基于每个品种的本地统计 GetWinRate(winCount, closedCount, includeEvens = false) => winTradeCount = winCount + (includeEvens ? 0 : 0) // 这里可根据需求添加平盘统计 closedCount > 0 ? (winTradeCount / closedCount) * 100 : na ATRCalc(length,highcalc,lowcalc,closecalc) => trueRange = na(highcalc[1])? highcalc-lowcalc : math.max(math.max(highcalc - lowcalc, math.abs(highcalc - closecalc[1])), math.abs(lowcalc - closecalc[1])) ta.rma(trueRange, length) getsymbolRate(symbol) => // 为当前品种初始化本地统计变量 var int winCount = 0 var int closedCount = 0 var float prevPositionSize = 0 CloseSym = request.security("BINANCE:"+symbol+".P","60", close) OpenSym = request.security("BINANCE:"+symbol+".P","60", open) LowSym = request.security("BINANCE:"+symbol+".P","60", low) HighSym = request.security("BINANCE:"+symbol+".P","60", high) [BBMID, BBUP, BBDOWN] = ta.bb(CloseSym, 20, 2) RSI = ta.rsi(CloseSym, 14) ATR = ATRCalc(14,HighSym,LowSym,CloseSym) longCondition = CloseSym > BBMID and OpenSym < BBMID and RSI > 52 var float TakeProfit = na var float StopLoss = na var bool PositionOpen = false // 跟踪交易平仓并统计胜负 currentPosition = strategy.position_size if prevPositionSize != 0 and currentPosition == 0 closedCount += 1 // 判断这笔交易是否盈利 if strategy.closedtrades.profit(strategy.closedtrades - 1) > 0 winCount += 1 prevPositionSize := currentPosition if longCondition and not PositionOpen Low = LowSym Close = CloseSym STOPPRICE = Low - ATR StopLoss := STOPPRICE SLPCT = ((Close - STOPPRICE) * 100) / STOPPRICE TPPCT = SLPCT * 2 PROFITPRICE = Close PROFITPRICE += PROFITPRICE * TPPCT / 100 TakeProfit := PROFITPRICE strategy.entry(symbol + "_Entry", strategy.long) // 为每个品种的订单添加唯一标识 PositionOpen := true if PositionOpen strategy.exit(symbol + "_Exit", symbol + "_Entry", stop=StopLoss, limit=TakeProfit) if strategy.position_size == 0 PositionOpen := false winrateSym = GetWinRate(winCount, closedCount) winrateSym BTCUSDT = getsymbolRate("BTCUSDT") ADAUSDT = getsymbolRate("ADAUSDT") DOTUSDT = getsymbolRate("DOTUSDT") INCHUSDT = getsymbolRate("1INCHUSDT") var tbl = table.new(position.top_right, 6, 11, frame_color=#151715, frame_width=1, border_width=2, border_color=color.new(color.white, 100)) if barstate.islastconfirmedhistory or barstate.isrealtime table.clear(tbl, 0, 0, 5, 10) table.cell(tbl, 0, 0, 'SYMBOL', text_halign = text.align_center, bgcolor = color.rgb(252, 252, 252), text_color = color.rgb(3, 3, 3), text_size = size.small) table.cell(tbl, 1, 0, 'WINRATE%', text_halign = text.align_center, bgcolor = color.rgb(255, 255, 255), text_color = color.rgb(0, 0, 0), text_size = size.small) table.cell(tbl, 3, 0, 'PNL', text_halign = text.align_center, bgcolor = color.rgb(255, 255, 255), text_color = color.rgb(7, 7, 7), text_size = size.small) // BTCUSDT行 table.cell(tbl,0,1,"BTCUSDT",text_halign = text.align_center, bgcolor = color.rgb(239, 255, 67), text_color = color.rgb(0, 0, 0), text_size = size.small) if not na(BTCUSDT) and BTCUSDT >= 50 table.cell(tbl,1,1,str.tostring(BTCUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(101, 255, 74), text_color = color.rgb(3, 3, 3), text_size = size.small) else table.cell(tbl,1,1,na(BTCUSDT) ? "N/A" : str.tostring(BTCUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(255, 74, 74), text_color = color.rgb(255, 255, 255), text_size = size.small) // ADAUSDT行 table.cell(tbl,0,2,"ADAUSDT",text_halign = text.align_center, bgcolor = color.rgb(239, 255, 67), text_color = color.rgb(0, 0, 0), text_size = size.small) if not na(ADAUSDT) and ADAUSDT >= 50 table.cell(tbl,1,2,str.tostring(ADAUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(101, 255, 74), text_color = color.rgb(3, 3, 3), text_size = size.small) else table.cell(tbl,1,2,na(ADAUSDT) ? "N/A" : str.tostring(ADAUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(255, 74, 74), text_color = color.rgb(255, 255, 255), text_size = size.small) // DOTUSDT行 table.cell(tbl,0,3,"DOTUSDT",text_halign = text.align_center, bgcolor = color.rgb(239, 255, 67), text_color = color.rgb(0, 0, 0), text_size = size.small) if not na(DOTUSDT) and DOTUSDT >= 50 table.cell(tbl,1,3,str.tostring(DOTUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(101, 255, 74), text_color = color.rgb(3, 3, 3), text_size = size.small) else table.cell(tbl,1,3,na(DOTUSDT) ? "N/A" : str.tostring(DOTUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(255, 74, 74), text_color = color.rgb(255, 255, 255), text_size = size.small) // 1INCHUSDT行 table.cell(tbl,0,4,"1INCHUSDT",text_halign = text.align_center, bgcolor = color.rgb(239, 255, 67), text_color = color.rgb(0, 0, 0), text_size = size.small) if not na(INCHUSDT) and INCHUSDT >= 50 table.cell(tbl,1,4,str.tostring(INCHUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(101, 255, 74), text_color = color.rgb(3, 3, 3), text_size = size.small) else table.cell(tbl,1,4,na(INCHUSDT) ? "N/A" : str.tostring(INCHUSDT,"0.00"),text_halign = text.align_center, bgcolor = color.rgb(255, 74, 74), text_color = color.rgb(255, 255, 255), text_size = size.small)
关键修改点说明
- 本地交易统计:在
getsymbolRate函数内添加了winCount和closedCount变量,单独统计当前品种的盈利交易数和总平仓交易数。 - 订单唯一标识:为每个品种的entry和exit订单添加了
symbol + "_"前缀,避免不同品种的订单互相干扰。 - 平仓胜负判断:通过跟踪
prevPositionSize和currentPosition的变化,检测交易平仓事件,然后通过strategy.closedtrades.profit判断这笔交易是否盈利,更新对应品种的统计数据。 - 空值处理:在表格显示时添加了
na判断,避免无交易时显示错误数值。
内容的提问来源于stack exchange,提问作者Welder Pasha
相关产品推荐
相关产品推荐

