这是一种称为超级趋势的趋势指标,显然可以得到非常准确的结果,结果与支持它的主要网站相匹配。
这种方法实际上使用计算出的ATR值作为输入,因为整个计算都是for循环,所以需要花费很多时间。
stockdata是一个具有Date,Open,High,Low,Close值的数据框,并将其作为输入传递。
输入结构(来自atr计算出的输出 - supert,supert1,supert3)是通过调用ST三次产生的输出,如果这是一个只能返回ST值的函数,可以很容易地附加到现有的数据帧中。
open high low close atr lband2 finaluband finaluband1 finaluband2 finallband finallband1 finallband2 supert supert1 supert2
date
01-07-02 5.2397 5.5409 5.2397 5.4127 NaN 0 0 0 0 0 0 0 0 0 0
02-07-02 5.5234 5.537 5.4214 5.4438 NaN 0 0 0 0 0 0 0 0 0 0
03-07-02 5.506 5.5458 5.3281 5.4661 NaN 0 0 0 0 0 0 0 0 0 0
04-07-02 5.5011 5.572 5.4175 5.5283 NaN 0 0 0 0 0 0 0 0 0 0
05-07-02 5.5633 5.6566 5.4749 5.5905 NaN 0 0 0 0 0 0 0 0 0 0
08-07-02 5.5011 5.7187 5.5011 5.6255 NaN 0 0 0 0 0 0 0 0 0 0
09-07-02 5.5905 5.7586 5.5681 5.6167 NaN 0 0 0 0 0 0 0 0 0 0
10-07-02 5.4885 5.4885 5.1465 5.2222 NaN 0 0 0 0 0 0 0 0 0 0
11-07-02 4.9784 5.2135 4.9784 5.1863 NaN 0 0 0 0 0 0 0 0 0 0
12-07-02 5.5011 5.5011 5.2446 5.3194 NaN 0 0 0 0 0 0 0 0 0 0
15-07-02 5.3243 5.4797 5.1912 5.333 0.24036 4.61437 5.57581 5.81617 6.05653 5.09509 4.85473 4.61437 5.57581 5.81617 6.05653
16-07-02 5.1999 5.4389 5.1999 5.3155 0.240224 4.598728 5.559624 5.799848 6.040072 5.09509 4.85473 4.61437 5.559624 5.799848 6.040072
17-07-02 4.7024 5.1377 4.6189 5.0445 0.285862 4.020715 5.164162 5.450023 5.735885 5.09509 4.85473 4.61437 5.164162 5.450023 5.735885
18-07-02 4.8803 5.1465 4.8356 5.0804 0.288365 4.125954 5.164162 5.450023 5.735885 4.702685 4.85473 4.61437 5.164162 5.450023 5.735885
19-07-02 5.027 5.2038 5.0221 5.1513 0.277699 4.279853 5.164162 5.450023 5.735885 4.835251 4.85473 4.61437 5.164162 5.450023 5.735885
22-07-02 5.0804 5.1465 4.9687 4.9735 0.268189 4.253033 5.164162 5.450023 5.735885 4.835251 4.85473 4.61437 5.164162 5.450023 5.735885
23-07-02 4.8181 5.0843 4.8181 5.0619 0.26799 4.14723 5.164162 5.450023 5.735885 4.835251 4.85473 4.61437 5.164162 5.450023 5.735885
24-07-02 5.058 5.129 4.9376 5.0619 0.260331 4.252307 5.164162 5.450023 5.735885 4.835251 4.85473 4.61437 5.164162 5.450023 5.735885
25-07-02 5.058 5.058 4.7918 4.8492 0.261308 4.140976 5.164162 5.447516 5.708824 4.835251 4.85473 4.61437 5.164162 5.447516 5.708824
26-07-02 5.1465 5.1465 4.7297 4.8715 0.276857 4.107528 5.164162 5.447516 5.708824 4.835251 4.384386 4.61437 5.164162 5.447516 5.708824
29-07-02 4.2235 4.2507 3.9038 4.2507 0.345941 3.039426 4.423191 4.769133 5.115074 4.835251 4.384386 4.61437 4.423191 4.769133 5.115074
30-07-02 4.17 4.3255 4.0369 4.2769 0.340207 3.160578 4.423191 4.769133 5.115074 3.840993 3.500785 3.160578 4.423191 4.769133 5.115074
31-07-02 4.1797 4.3031 4.1486 4.2108 0.321637 3.26094 4.423191 4.769133 5.115074 3.904213 3.582577 3.26094 4.423191 4.769133 5.115074
01-08-02 4.2507 4.5169 4.2507 4.4586 0.320083 3.423551 4.423191 4.769133 5.115074 4.063717 3.743634 3.423551 4.063717 4.769133 5.115074
02-08-02 4.068 4.6101 4.068 4.4984 0.342285 3.312196 4.681335 4.769133 5.115074 4.063717 3.743634 3.423551 4.063717 4.769133 5.115074
05-08-02 4.5965 4.7918 4.5256 4.7918 0.337396 3.646511 4.681335 4.769133 5.115074 4.321304 3.983908 3.646511 4.321304 3.983908 5.115074
06-08-02 4.6276 4.6811 4.6276 4.65 0.320077 3.69412 4.974427 5.294503 5.115074 4.334273 4.014197 3.69412 4.334273 4.014197 5.115074
07-08-02 4.8006 4.854 4.6587 4.752 0.308469 3.830943 4.974427 5.294503 5.115074 4.447881 4.139412 3.830943 4.447881 4.139412 5.115074
08-08-02 4.7918 4.7918 4.614 4.65 0.295402 3.816694 4.974427 5.293704 5.115074 4.447881 4.139412 3.830943 4.447881 4.139412 5.115074
09-08-02 4.6587 4.7024 4.5742 4.7024 0.278682 3.802255 4.916982 5.195664 5.115074 4.447881 4.139412 3.830943 4.447881 4.139412 5.115074
如何重写此代码,以便在不使用for循环的情况下,可以在不影响准确性的情况下实现相同的结果。我希望单个函数调用将pandas dataframe格式中的“supert”值添加到stockdata。
def ST(high, low, close, atr, prevfinaluband, prevfinallband, prevsupertrend,
prevclose, multiplier):
upperbasicband = ((high+low)/2 + (multiplier * atr))
lowerbasicband = ((high+low)/2 - (multiplier * atr))
if upperbasicband < prevfinaluband or prevclose > prevfinaluband:
upperband = upperbasicband
else:
upperband = prevfinaluband
if lowerbasicband > prevfinallband or prevclose < prevfinallband:
lowerband = lowerbasicband
else:
lowerband = prevfinallband
if prevsupertrend == prevfinaluband:
if close <= upperband:
supertrend = upperband
else:
supertrend = lowerband
else:
if prevsupertrend == prevfinallband:
if close >= lowerband:
supertrend = lowerband
else:
supertrend = upperband
else:
supertrend = 0.0
return upperbasicband, lowerbasicband, upperband, lowerband, supertrend
for i in range(1, len(stockdata)):
if np.isnan(stockdata['atr'][i]):
continue
uband, lband, finaluband, finallband, supert =\
customindicator.ST(stockdata['high'][i], stockdata['low'][i],
stockdata['close'][i], stockdata['atr'][i],
stockdata['finaluband'][i-1], stockdata['finallband'][i-1],
stockdata['supert'][i-1], stockdata['close'][i-1],
multiplier =7)
我正在尝试这种优化,以便它能够更快地运行。我可以将参数传递给函数。如果您有解决方案,请发布。
答案 0 :(得分:0)
在给定的ST实现中,我无法在给定样本中重现结果。遗憾。
但我更新了代码以返回与示例中相同的形状并跳过NaN。
矢量化将为您带来巨大的改进。与 31.4毫秒矢量化版本相比, 14.9秒原始样本为10 ** 5值。
#generate sample
n = 10**5
stockdata = pd.DataFrame(np.random.randint(0,100,size=(n,7)),
columns = ['atr','high', 'low','close','finaluband','finallband','supert'])
print (stockdata.shape)
stockdata.head()
SuperST将返回DataFrame
上的所有stockdata
for i in range(3)
它恰好是不同乘法的循环,您可以将其重写为for i in [7,8,9]: SuperST(stockdata,estim,i)
你的ST实现取决于之前通话的结果。它使用'finaluband','finallband','supert'
并自行返回。最初它们是零,但在第一次调用后它们会有一些价值。因此estim
可以让您控制这种情况,您可以使用之前调用的结果或初始零来调用SuperST
。只需使用零重命名初始DataFrame并将其传递给SuperST
。
df_res = stockdata
estim = pd.DataFrame(np.zeros((df_res.shape[0],5)), index = df_res.index,
columns=['uband', 'lband', 'finaluband', 'finallband', 'supert'])
for i in range(3):
estim = SuperST(stockdata,estim)
df_res = df_res.join(estim,rsuffix="{}".format(i))
print(df_res[['open', 'high', 'low', 'close', 'atr', 'lband2', 'finaluband',
'finaluband1', 'finaluband2', 'finallband', 'finallband1',
'finallband2', 'supert', 'supert1', 'supert2']])
SuperST与ST相同
def SuperST(stockdata,estim,multiplier = 7):
#first we need next row value
df_prev = estim[['finaluband','finallband','supert']].join(stockdata[['close']]).shift(1)
# name colums as it was in paramas
df_prev.columns = ['prevfinaluband', 'prevfinallband', 'prevsupertrend', 'prevclose']
# working matrix parmas with shifed values w/o NaN in ATR
df = stockdata.dropna().join(df_prev).fillna(0)
#calulate vectors
upperbasicband = ((df.high+df.low)/2 + (multiplier * df.atr))
lowerbasicband = ((df.high+df.low)/2 - (multiplier * df.atr))
# np.where is a vector version of if
upperband = np.where((upperbasicband < df.prevfinaluband) | (df.prevclose > df.prevfinaluband),
upperbasicband,df.prevfinaluband)
lowerband = np.where ((lowerbasicband > df.prevfinallband) | (df.prevclose < df.prevfinallband),
lowerbasicband,df.prevfinallband)
supertrend = np.where (df.prevsupertrend == df.prevfinaluband,
np.where(df.close <= upperband,
upperband,lowerband),
np.where(df.prevsupertrend == df.prevfinallband,
np.where(df.close >= lowerband,
lowerband,upperband),
np.zeros_like(lowerband)))
return upperbasicband.to_frame('uband').assign(
lband = lowerbasicband).assign(
finaluband = upperband).assign(
finallband = lowerband).assign(
supert = supertrend)