使用pandas python的SuperTrend代码

o8x7eapl  于 2023-05-19  发布在  Python
关注(0)|答案(3)|浏览(154)

我试图使用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上找到已发布的代码!

a8jjtwal

a8jjtwal1#

SuperTrend指标包含在pandas_ta中,您可以简单地:

import pandas_ta as ta

sti = ta.supertrend(df['High'], df['Low'], df['Close'], length=7, multiplier=3)

假设df是一个带有OHLC价格的pandas DataFrame,结果sti是一个带有4列的DataFrame:
1.趋势
1.方向
1.长的
1.短
其中趋势是长线和短线的连接。请注意,列标题是动态的,包含长度和乘数参数值。

j2qf4p5b

j2qf4p5b2#

使用此完整代码

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"
1wnzp6jl

1wnzp6jl3#

我知道这是一个老线程,但有人试图通过避免for循环来提高性能吗?超级趋势函数中的for循环是一个大的下降,需要超过10分钟来计算。

相关问题