You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pine Script如何基于ATR与账户权益设置自定义开仓仓位

问题原因

策略运行报错和strategy.equity用法无关,核心是三个逻辑错误:

  • 仓位计算时机完全倒置:当前代码里的止损距离differenceLong/differenceShort依赖开仓后才会更新的strategy.position_avg_price、开仓完成后才赋值的atr_at_entry计算。当buy/sell信号触发、strategy.entry准备执行下单的瞬间,账户还没有持仓,上述两个值全为na空值,空仓阶段两个差值还会出现0值,直接触发「除以空值」「除以零」的运行时错误,导致策略崩溃。
  • 风险比例未做单位转换:输入参数risk是百分比单位(比如输入1代表1%风险),直接和权益相乘会把风险金额放大100倍,不符合预设的仓位计算逻辑。
  • 仓位值未做合法性校验:Pine Script要求strategy.entry的qty参数必须为合法正数,传入na、0、负数、非整数值(部分交易品种不支持碎合约)都会触发运行错误。
修复方法
  1. 先把百分比形式的风险输入转换为小数比例,避免风险金额计算错误。
  2. 把止损距离的计算提前到开仓信号触发前:信号出现时直接取当前K线的ATR跟踪止损值作为预设止损位,以当根价格为基准计算止损距离,不需要等开仓完成后再从持仓数据里取值。
  3. 给仓位计算增加兜底逻辑:先判断止损距离大于0再计算仓位,计算完成后做取整、正数校验,过滤非法值。
  4. 调整atr_at_entry的赋值逻辑,信号触发当根就记录止损值,方便后续止盈止损计算。
修正后完整代码
//@version=4
//CREDITS to HPotter for the orginal code. The guy trying to sell this as his own is a scammer lol. 

// Calculate start/end date and time condition
startDate  = input(timestamp("2022-06-20T00:00:00"), type = input.time)
finishDate = input(timestamp("2022-12-01T00:00:00"), type = input.time)
 
time_cond  = time >= startDate and time <= finishDate

// Inputs
src = close 

keyvalue = input(2.5, title = "Frequência", step = .5)
atrperiod = 15
xATR = atr(atrperiod)
nLoss = keyvalue * xATR
// 百分比风险转小数
risk = input(1, title="Capital Risk (%)") / 100
rr = input(1, title="Risk Reward Ratio", step = 0.5)

//Calculate atr metrics
xATRTrailingStop = 0.0
xATRTrailingStop := iff(src > nz(xATRTrailingStop[1], 0) and src[1] > nz(xATRTrailingStop[1], 0), max(nz(xATRTrailingStop[1]), src - nLoss),
   iff(src < nz(xATRTrailingStop[1], 0) and src[1] < nz(xATRTrailingStop[1], 0), min(nz(xATRTrailingStop[1]), src + nLoss), 
   iff(src > nz(xATRTrailingStop[1], 0), src - nLoss, src + nLoss)))
 
pos = 0   
pos :=  iff(src[1] < nz(xATRTrailingStop[1], 0) and src > nz(xATRTrailingStop[1], 0), 1,
   iff(src[1] > nz(xATRTrailingStop[1], 0) and src < nz(xATRTrailingStop[1], 0), -1, nz(pos[1], 0))) 
   
xcolor = pos == -1 ? color.red: pos == 1 ? color.green : color.blue

plot(xATRTrailingStop, color = xcolor, title = "Trailing Stop")
buy = crossover(src,xATRTrailingStop)
sell = crossunder(src,xATRTrailingStop)

plotshape(buy, title = "Buy", text = 'Buy', style = shape.labelup, location = location.belowbar, color= color.green,textcolor = color.white, transp = 0, size = size.tiny)
plotshape(sell, title = "Sell", text = 'Sell', style = shape.labeldown, color= color.red,textcolor = color.white, transp = 0, size = size.tiny)


// 信号触发当根提前记录止损值,计算开仓所需参数
var float atr_at_entry = na
// 提前计算当根信号对应的多空止损距离
long_dist = buy ? (src - xATRTrailingStop) : na
short_dist = sell ? (xATRTrailingStop - src) : na
// 计算合法仓位值,兜底处理非法情况
long_pos = buy and long_dist > 0 ? math.max(1, math.round((strategy.equity * risk) / long_dist)) : na
short_pos = sell and short_dist > 0 ? math.max(1, math.round((strategy.equity * risk) / short_dist)) : na

// 开仓时记录止损价
if buy and time_cond
    atr_at_entry := xATRTrailingStop
if sell and time_cond
    atr_at_entry := xATRTrailingStop

// 持仓阶段计算止盈价格
longExitPrice  = strategy.position_size > 0 ? strategy.position_avg_price + ((strategy.position_avg_price - atr_at_entry) * rr) : na
shortExitPrice = strategy.position_size < 0 ? strategy.position_avg_price - ((atr_at_entry - strategy.position_avg_price) * rr) : na

// 传入合法仓位值开仓
strategy.entry("long",   true, when = buy and time_cond, qty=long_pos)
strategy.entry("short", false, when = sell and time_cond, qty=short_pos)

if (strategy.position_size > 0)
    strategy.exit(id="TP", limit = longExitPrice)
        
if (strategy.position_size < 0)
    strategy.exit(id="TP", limit = shortExitPrice)
补充说明

修正后的代码完全匹配预设仓位计算公式:(账户权益 * 风险比例) / 入场价到ATR止损线的距离,默认加了最小1手的兜底限制,避免计算结果小于交易所最小下单单位。若交易品种支持小数合约,可将math.round替换为math.round_to_mintick,自动适配品种最小报价单位对应的合约精度。

内容的提问来源于stack exchange,提问作者Rayhan Brito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:30:53