如何用Pandas高效实现Pine Script布林带宽百分位的循环逻辑?
布林带宽百分位(BBWP)Pandas实现优化
核心问题
你当前代码用硬编码的shift(-1)、shift(-2)等操作统计过去BBW值,但无法动态适配每行对应的回溯长度(最多252期,不足252期则取已有所有前期数据)。我们需要实现动态窗口,统计当前BBW值在过去min(当前索引,252)期内的百分位排名(即有多少前期BBW值小于等于当前值)。
优化后的代码
import numpy as np import pandas as pd import pandas_ta as ta import yfinance as yf # 获取BTC数据 btc = yf.Ticker("BTC-USD") df = btc.history(start="2022-06-08", interval="15m", actions=False) # 重置索引为数字索引(匹配Pine Script的bar_index逻辑) df.reset_index(drop=True, inplace=True) # 计算基础指标 df["BASIS"] = ta.sma(df.Close, length=13) df["STDEV"] = ta.stdev(df.Close, length=13) df["BBW"] = (df["BASIS"] + df["STDEV"] - (df["BASIS"] - df["STDEV"])) / df["BASIS"] # 计算每个行对应的回溯长度 df["BBWLEN"] = np.where(df.index < 252, df.index, 252) # 动态计算BBWSUM:统计过去BBWLEN期内BBW <= 当前BBW的数量 bbw_values = df["BBW"].values bbw_sum = np.zeros(len(df), dtype=int) for i in range(len(df)): window_len = df["BBWLEN"].iloc[i] if window_len == 0: continue # 索引0时无前期数据,sum为0 # 取前期window_len个BBW值 window = bbw_values[i - window_len : i] # 统计小于等于当前BBW的数量 bbw_sum[i] = (window <= bbw_values[i]).sum() df["BBWSUM"] = bbw_sum # 计算BBWP百分位 df["BBWP"] = np.where(df.index >= 13, (df["BBWSUM"] / df["BBWLEN"]) * 100, None) # 查看结果 print(df[["BASIS", "STDEV", "BBW", "BBWLEN", "BBWSUM", "BBWP"]].tail())
代码说明
- 索引重置:用
reset_index(drop=True)替代手动生成索引,更简洁可靠。 - 动态窗口计算:通过循环遍历每行,根据
BBWLEN取对应长度的前期BBW数据,利用numpy向量化操作统计符合条件的数量,效率远高于硬编码多个shift。 - 结果兼容:完全匹配Pine Script逻辑,仅在索引>=13时计算BBWP,其余位置设为None。
内容的提问来源于stack exchange,提问作者jzacharuk
相关产品推荐
相关产品推荐

