使用 pandas python 的 SuperTrend 代码
Posted
技术标签:
【中文标题】使用 pandas python 的 SuperTrend 代码【英文标题】:SuperTrend code using pandas python 【发布时间】:2017-12-09 15:44:40 【问题描述】:我正在尝试使用 pandas 在 python 中为 SuperTrend 指标编写以下算法。
BASIC UPPERBAND = (HIGH + LOW) / 2 + Multiplier * ATR
BASIC LOWERBAND = (HIGH + LOW) / 2 - Multiplier * ATR
FINAL UPPERBAND = IF( (Current BASICUPPERBAND < Previous FINAL UPPERBAND) or (Previous Close > Previous FINAL UPPERBAND))
THEN (Current BASIC UPPERBAND) ELSE Previous FINALUPPERBAND)
FINAL LOWERBAND = IF( (Current BASIC LOWERBAND > Previous FINAL LOWERBAND) or (Previous Close < Previous FINAL LOWERBAND))
THEN (Current BASIC LOWERBAND) ELSE Previous FINAL LOWERBAND)
SUPERTREND = IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close <= Current FINAL UPPERBAND)) THEN
Current FINAL UPPERBAND
ELSE
IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close > Current FINAL UPPERBAND)) THEN
Current FINAL LOWERBAND
ELSE
IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close >= Current FINAL LOWERBAND)) THEN
Current FINAL LOWERBAND
ELSE
IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close < Current FINAL LOWERBAND)) THEN
Current FINAL UPPERBAND
这是我编写和测试的代码:
# Compute basic upper and lower bands
df['basic_ub'] = (df['high'] + df['low']) / 2 + multiplier * df[atr]
df['basic_lb'] = (df['high'] + df['low']) / 2 - multiplier * df[atr]
# Compute final upper and lower bands
for i in range(0, len(df)):
if i < period:
df.set_value(i, 'basic_ub', 0.00)
df.set_value(i, 'basic_lb', 0.00)
df.set_value(i, 'final_ub', 0.00)
df.set_value(i, 'final_lb', 0.00)
else:
df.set_value(i, 'final_ub', (df.get_value(i, 'basic_ub')
if df.get_value(i, 'basic_ub') < df.get_value(i-1, 'final_ub') or df.get_value(i-1, 'close') > df.get_value(i-1, 'final_ub')
else df.get_value(i-1, 'final_ub')))
df.set_value(i, 'final_lb', (df.get_value(i, 'basic_lb')
if df.get_value(i, 'basic_lb') > df.get_value(i-1, 'final_lb') or df.get_value(i-1, 'close') < df.get_value(i-1, 'final_lb')
else df.get_value(i-1, 'final_lb')))
# Set the Supertrend value
for i in range(0, len(df)):
if i < period:
df.set_value(i, st, 0.00)
else:
df.set_value(i, 'st', (df.get_value(i, 'final_ub')
if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_ub')) and (df.get_value(i, 'close') <= df.get_value(i, 'final_ub')))
else (df.get_value(i, 'final_lb')
if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_ub')) and (df.get_value(i, 'close') > df.get_value(i, 'final_ub')))
else (df.get_value(i, 'final_lb')
if ((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_lb')) and (df.get_value(i, 'close') >= df.get_value(i, 'final_lb')))
else (df.get_value(i, 'final_ub')
if((df.get_value(i-1, 'st') == df.get_value(i-1, 'final_lb')) and (df.get_value(i, 'close') < df.get_value(i, 'final_lb')))
else 0.00
)
)
)
)
)
# Mark the trend direction up/down
df['stx'] = np.where((df['st'] > 0.00), np.where((df['close'] < df['st']), 'down', 'up'), np.NaN)
我工作,但我对 for 循环不满意。谁能帮忙优化一下?
你可以在Github找到发布的代码!
【问题讨论】:
请为您的问题添加格式。 好的,下次我会添加格式。看起来这次有人代表我做了。谢谢 伟大的@arkochhar!欢迎来到 SO。 查看shift
。它应该让你走上正轨。
感谢您的意见@acushner。我试过shift
。我用df['final_ub'] = np.where(np.logical_or(df['basic_ub'] < df['final_ub'].shift(), df['close'].shift() > df['final_ub'].shift()), df['basic_ub'], df['final_ub'].shift())
和df['final_lb'] = np.where(np.logical_or(df['basic_lb'] > df['final_lb'].shift(), df['close'].shift() < df['final_lb'].shift()), df['basic_lb'], df['final_lb'].shift())
替换了上面。但是我需要初始化df['final_ub'] = 0.00
和df['final_lb'] = 0.00
,否则我会得到KeyError
异常。但结果完全不正确。我还在调试有什么想法吗?
【参考方案1】:
SuperTrend Indicator 包含在pandas_ta 中,您可以在其中简单地:
import pandas_ta as ta
sti = ta.supertrend(df['High'], df['Low'], df['Close'], 7, 3)
鉴于df
是一个带有 OHLC 价格的 pandas DataFrame。结果 sti
是一个有 4 列的 DataFrame:
-
趋势
方向
长
短
趋势是多线和空线的串联。请注意,列标题是动态的,包含长度和乘数参数值。
【讨论】:
我的传递长度为 7,但我只获取最后 4 行的数据,所有其他行都是 nan 值,你能解释一下原因吗? 您的 DF 中总共有多少行? 我只有 11 行的每个高低和收盘 如果你能告诉我每个的最小行值有多少,应该传递高低关闭以获得准确的超级趋势值?因为当我传递 11 行时,我得到的值与传递 60 行不同.. 11 - 我是这么想的,因为这个指标是基于使用滚动窗口统计的 ATR,所以它在系列开始时作为缺失值。【参考方案2】:使用这个完整的代码
import numpy as np
import yfinance as yf
import pandas_datareader as pdr
import pandas as pd
data =yf.download("ACC.NS", period="1d",interval="5m")
data=data.reset_index(drop=True)
data['tr0'] = abs(data["High"] - data["Low"])
data['tr1'] = abs(data["High"] - data["Close"].shift(1))
data['tr2'] = abs(data["Low"]- data["Close"].shift(1))
data["TR"] = round(data[['tr0', 'tr1', 'tr2']].max(axis=1),2)
data["ATR"]=0.00
data['BUB']=0.00
data["BLB"]=0.00
data["FUB"]=0.00
data["FLB"]=0.00
data["ST"]=0.00
# Calculating ATR
for i, row in data.iterrows():
if i == 0:
data.loc[i,'ATR'] = 0.00#data['ATR'].iat[0]
else:
data.loc[i,'ATR'] = ((data.loc[i-1,'ATR'] * 13)+data.loc[i,'TR'])/14
data['BUB'] = round(((data["High"] + data["Low"]) / 2) + (2 * data["ATR"]),2)
data['BLB'] = round(((data["High"] + data["Low"]) / 2) - (2 * data["ATR"]),2)
# FINAL UPPERBAND = IF( (Current BASICUPPERBAND < Previous FINAL UPPERBAND) or (Previous Close > Previous FINAL UPPERBAND))
# THEN (Current BASIC UPPERBAND) ELSE Previous FINALUPPERBAND)
for i, row in data.iterrows():
if i==0:
data.loc[i,"FUB"]=0.00
else:
if (data.loc[i,"BUB"]<data.loc[i-1,"FUB"])|(data.loc[i-1,"Close"]>data.loc[i-1,"FUB"]):
data.loc[i,"FUB"]=data.loc[i,"BUB"]
else:
data.loc[i,"FUB"]=data.loc[i-1,"FUB"]
# FINAL LOWERBAND = IF( (Current BASIC LOWERBAND > Previous FINAL LOWERBAND) or (Previous Close < Previous FINAL LOWERBAND))
# THEN (Current BASIC LOWERBAND) ELSE Previous FINAL LOWERBAND)
for i, row in data.iterrows():
if i==0:
data.loc[i,"FLB"]=0.00
else:
if (data.loc[i,"BLB"]>data.loc[i-1,"FLB"])|(data.loc[i-1,"Close"]<data.loc[i-1,"FLB"]):
data.loc[i,"FLB"]=data.loc[i,"BLB"]
else:
data.loc[i,"FLB"]=data.loc[i-1,"FLB"]
# SUPERTREND = IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close <= Current FINAL UPPERBAND)) THEN
# Current FINAL UPPERBAND
# ELSE
# IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close > Current FINAL UPPERBAND)) THEN
# Current FINAL LOWERBAND
# ELSE
# IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close >= Current FINAL LOWERBAND)) THEN
# Current FINAL LOWERBAND
# ELSE
# IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close < Current FINAL LOWERBAND)) THEN
# Current FINAL UPPERBAND
for i, row in data.iterrows():
if i==0:
data.loc[i,"ST"]=0.00
elif (data.loc[i-1,"ST"]==data.loc[i-1,"FUB"]) & (data.loc[i,"Close"]<=data.loc[i,"FUB"]):
data.loc[i,"ST"]=data.loc[i,"FUB"]
elif (data.loc[i-1,"ST"]==data.loc[i-1,"FUB"])&(data.loc[i,"Close"]>data.loc[i,"FUB"]):
data.loc[i,"ST"]=data.loc[i,"FLB"]
elif (data.loc[i-1,"ST"]==data.loc[i-1,"FLB"])&(data.loc[i,"Close"]>=data.loc[i,"FLB"]):
data.loc[i,"ST"]=data.loc[i,"FLB"]
elif (data.loc[i-1,"ST"]==data.loc[i-1,"FLB"])&(data.loc[i,"Close"]<data.loc[i,"FLB"]):
data.loc[i,"ST"]=data.loc[i,"FUB"]
# Buy Sell Indicator
for i, row in data.iterrows():
if i==0:
data["ST_BUY_SELL"]="NA"
elif (data.loc[i,"ST"]<data.loc[i,"Close"]) :
data.loc[i,"ST_BUY_SELL"]="BUY"
else:
data.loc[i,"ST_BUY_SELL"]="SELL"
【讨论】:
您也可以使用 for comprehensions 或 applymap 或 apply(在行上)。在你的 for 循环中你从不使用row
,你可以删除它。以上是关于使用 pandas python 的 SuperTrend 代码的主要内容,如果未能解决你的问题,请参考以下文章